André Alves de Lima

Talking about Software Development and more…

Criando SplashScreens estendidas em Aplicações para a Windows Store

Olá pessoal, tudo certo?

Continuando a série de posts sobre o desenvolvimento de aplicativos para a Windows Store (Metro Style Apps), no artigo de hoje vou falar sobre as SplashScreens estendidas. Se você ainda não sabe, os aplicativos da nova interface do Windows 8 devem ser obrigatoriamente inicializados em até 15 segundos (essa mesma regra vale no iOS também, ou estou errado?). Se isso não acontecer, seu aplicativo é fechado automaticamente pelo sistema operacional.

Para assegurar que isso não aconteca com a sua aplicação e para melhorar a experiência de carregamento dela, você pode criar um mecanismo para estender a SplashScreen. Dessa forma, ao invés de exibir diretamente a página principal do seu aplicativo após a SplashScreen, você pode exibir uma página semelhante à SplashScreen com uma ProgressBar (ou ProgressRing), onde você vai fazer toda a inicialização necessária da sua aplicação.

Esse artefato é utilizado na maioria dos aplicativos para a Windows Store, inclusive nos aplicativos que vêm pré-instalados com o Windows 8. Por exemplo, o próprio aplicativo de notícias do Windows 8, ao ser carregado, mostra uma SplashScreen estendida com uma ProgressRing:


Entendeu a ideia? Então vamos agora aprender como fazer uma SplashScreen estendida na nossa aplicação. O código apresentado neste artigo foi baseado no tópico da MSDN sobre esse mesmo assunto, o qual eu simplifiquei em alguns pontos e adicionei alguns detalhes que achei necessário.

Para começar, vamos criar um novo projeto do tipo Windows Store Blank App (XAML), chamado de SplashEstendida, por exemplo. Neste projeto, a primeira coisa que vamos fazer é adicionar outra Blank Page que fará o papel de SplashScreen estendida. Vamos chamar essa nova página de SplashPage.

O XAML dessa página será bem simples. Basicamente precisamos ficar atentos a três detalhes:

  • O Background do Grid deve ter a mesma cor do Background da sua SplashScreen
  • Um controle Image deve ser adicionado dentro do Grid e o Source dessa Image deve apontar para a mesma imagem utilizada na SplashScreen
  • Um controle de ProgressRing ou ProgressBar deve ser adicionado para indicar que algo está sendo processado

Vejamos como deve ficar o XAML da parte interna da nossa Page:

    <Grid Background="#464646">
        <Image x:Name="SplashImage" Source="Assets/SplashScreen.png" VerticalAlignment="Center" HorizontalAlignment="Center" Height="300" Width="620"/>
        <ProgressRing x:Name="SplashProgress" IsActive="True" Height="40" Width="40" Foreground="White" HorizontalAlignment="Center" Margin="0,520,0,230"/>
    </Grid>

Agora que já temos o XAML definido para a nossa SplashScreen estendida, chegou a hora de customizarmos o comportamento dessa janela. No code-behind dessa Page, precisamos lidar com os seguintes itens:

  • A imagem da SplashScreen estendida deve ser reposicionada quando ocorrer uma mudança de estado visual (quando o usuário altera para o modo snapped, por exemplo)
  • O carregamento dos recursos da nossa aplicação deve ser feito assim que a SplashScreen estendida for exibida

Vamos atacar primeiramente a questão do reposicionamento da imagem quando ocorrer uma mudança de estado visual. Para solucionar esse item, vamos precisar de um atributo do tipo SplashScreen (veremos mais pra frente como esse atributo será inicializado no construtor da nossa SplashPage), um event handler para o evento SizeChanged da nossa Page e um método que fará o redimensionamento da imagem apropriadamente. Então, vamos adicionar o seguinte código no code-behind da nossa SplashPage:

        /// <summary>
        /// Atributo que armazena uma referência à SplashScreen da aplicacao. Esse atributo é inicializado no construtor da SplashPage.
        /// </summary>
        private Windows.ApplicationModel.Activation.SplashScreen _splash;

        /// <summary>
        /// Handler para o evento SizeChanged da SplashPage. Aqui nós chamamos o método PosicionarImagem, que vai posicionar apropriadamente a SplashImage
        /// de acordo com o estado visual corrente (snapped, full, etc).
        /// </summary>
        /// <param name="sender">O objeto que invocou o evento SizeChanged.</param>
        /// <param name="e">Informacoes sobre o evento SizeChanged.</param>
        void SplashPage_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
        {
            PosicionarImagem();
        }

        /// <summary>
        /// Posiciona a SplashImage apropriadamente de acordo com o estado visual corrente (snapped, full, etc).
        /// </summary>
        void PosicionarImagem()
        {
            if (_splash != null)
            {
                Rect splashImageRect = _splash.ImageLocation;

                SplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X);
                SplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
                SplashImage.Height = splashImageRect.Height;
                SplashImage.Width = splashImageRect.Width;
            }
        }

Agora, como próximo passo, precisamos criar um construtor especializado na nossa SplashPage, que receberá a SplashScreen original do aplicativo e fará a inicialização necessária de outras informações. Além disso, vamos criar também um event handler para o evento Dismissed da SplashScreen, que é o lugar onde colocaremos o código para fazer o carregamento de recursos da nossa aplicação e navegar para a página principal quando o carregamento estiver concluído:

        /// <summary>
        /// Frame que será criado no construtor da SplashPage para ser utilizado posteriormente na navegação à página inicial do aplicativo.
        /// </summary>
        Frame rootFrame;

        /// <summary>
        /// Construtor que adicionalmente recebe a SplashScreen da aplicação.
        /// </summary>
        /// <param name="splash">A SplashScreen da aplicação.</param>
        public SplashPage(Windows.ApplicationModel.Activation.SplashScreen splash) : this()
        {
            Window.Current.SizeChanged += SplashPage_SizeChanged;

            _splash = splash;
            if (_splash != null)
            {
                _splash.Dismissed += DismissedEventHandler;
                PosicionarImagem();
            }

            // Criando um Frame no construtor para ser utilizado na navegação para a página principal do aplicativo.
            rootFrame = new Frame();
        }

        /// <summary>
        /// Handler assíncrono que fará o trabalho de carregamento dos recursos da aplicação e navegará para a página principal quando tiver concluído.
        /// </summary>
        /// <param name="sender">A SplashScreen da aplicação.</param>
        /// <param name="e">Informações sobre o evento Dismissed da SplashScreen.</param>
        async void DismissedEventHandler(Windows.ApplicationModel.Activation.SplashScreen sender, object e)
        {
            // Neste ponto você deve fazer o carregamento de recursos da sua aplicação. 
            // Como se trata de um exemplo, estamos somente fazendo a thread esperar 3 segundos antes de prosseguir.
            new System.Threading.ManualResetEvent(false).WaitOne(3000);

            // Quando o carregamento estiver concluído, navegamos para a página principal do aplicativo.
            await rootFrame.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                rootFrame.Navigate(typeof(MainPage), true);
                Window.Current.Content = rootFrame;
            });
        }

Finalmente, como última etapa, precisamos substituir o código presente no método OnLaunched da nossa classe App. Para isso, abra o arquivo App.xaml.cs e substitua o código desse método pelo conteúdo abaixo, que vai substituir o comportamento original e chamar a nossa SplashPage após a exibição da Splash Screen original da aplicação:

        protected override void OnLaunched(LaunchActivatedEventArgs args)
        {
            if (args.PreviousExecutionState != ApplicationExecutionState.Running)
            {
                bool loadState = (args.PreviousExecutionState == ApplicationExecutionState.Terminated);
                SplashPage extendedSplash = new SplashPage(args.SplashScreen);
                Window.Current.Content = extendedSplash;
            }

            Window.Current.Activate();
        }

Execute a aplicação e veja que a SplashPage é exibida e, após os três segundos que colocamos de espera, ocorre a navegação para a MainPage.

EDIT: Caso você tenha interesse em exibir a splash screen estendida somente na primeira vez que o aplicativo for executado, confira aqui um artigo que eu escrevi solucionando essa questão.

É isso aí, espero que vocês tenham gostado de mais esse exemplo envolvendo apps para o Windows 8. O código do exemplo está disponível na MSDN Code Gallery.

Até a próxima!

André Lima

2 thoughts on “Criando SplashScreens estendidas em Aplicações para a Windows Store

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *