Questões de mobilidade

Navegação no Windows Phone: noções básicas

Yochay Kiriaty

Baixar o código de exemplo

Os aplicativos Silverlight para Windows Phone têm um modelo de página parecido com as da Web em que os usuários finais navegam entre páginas. Há um botão Voltar de hardware dedicado que facilita o retorno a páginas anteriores (sem consumir espaço na tela), e o registro em diário (ou histórico) da navegação é integrado com a plataforma para facilitar a navegação ou a transição entre diferentes aplicativos. Este artigo de duas partes:

  • Apresentará a você o modelo de navegação em páginas do Windows Phone.
  • Apresentará as práticas recomendadas de que você precisará para tirar o máximo proveito das APIs atuais – como integração com o botão Voltar do hardware, carregamento e descarregamento de páginas otimizados e assegurar que o seu modelo de navegação atenda às diretrizes de certificação do Windows Phone.
  • Apresentará receitas práticas e fáceis de seguir para criar as navegações mais complexas não implementadas com as APIs atuais, incluindo conteúdo temporário e transições de página.

Modelo de navegação do Windows Phone

O modelo de navegação do Windows Phone é formado por um quadro (PhoneApplicationFrame) e uma ou mais páginas (PhoneApplicationPage) que armazenam o conteúdo carregado no quadro.

PhoneApplicationFrame expõe a maioria dos eventos de navegação e também o método Navigate que você usará para percorrer as páginas. Ele também determina a área de cliente para o aplicativo e reserva o espaço para a barra de aplicativo e a bandeja do sistema. 

PhoneApplicationPage tem notificações específicas de página para quando uma página é acessada e quando o usuário sai de uma página. Também processa eventos relacionados ao botão Voltar do hardware.

Tanto PhoneApplicationFrame quanto PhoneApplicationPage compartilham um NavigationService; esse serviço, na verdade, é fazer a navegação. O Windows Phone permite registrar em diário (controlar o histórico de páginas carregadas para que você possa voltar a uma página anterior) e expõe APIs para que você possa retornar. Não há suporte para navegação progressiva no telefone.

O Windows Phone tem três botões de hardware dedicado: Voltar, Iniciar e Pesquisar. Existem requisitos de certificação de aplicativo específicos sobre como trabalhar com o botão Voltar do hardware:

  • Um aplicativo não deve impedir o usuário de voltar a uma página anterior. A única exceção possível é um prompt quando há perda de dados envolvida – nesse caso, você pode pedir a confirmação e permitir que o usuário navegue de volta se assim ele desejar.
  • Se um pop-up, o painel de entrada do software (SIP, Software Input Panel) ou outra caixa de diálogo temporária estivessem abertos, pressionar o botão Voltar do hardware ignoraria a caixa de diálogo, mas não sairia da página atual (efetivamente cancelando a navegação com o botão Voltar).
  • Pressionar o botão Voltar quando na primeira tela de um aplicativo faz com que o usuário saia do aplicativo. Essa funcionalidade é oferecida gratuitamente. Se você não impede a navegação, a estrutura sai para você – na verdade, essa é a única maneira de sair de um aplicativo Silverlight. Não há um método Exit nas APIs expostas.
  • Para manter uma experiência de usuário (UX, User Experience) consistente entre os aplicativos, o botão Voltar só deve ser usado para navegação regressiva.

Além da função crucial do botão Voltar na navegação, o botão Iniciar também participa da navegação. Quando o usuário pressiona o botão Iniciar, o aplicativo que está sendo executado é desativado e ocorre uma alternância de contexto quando você navega com esse botão. Desse ponto, o usuário pode iniciar outro aplicativo e navegar nele ou pode optar por retornar (usando o botão Voltar do hardware) ao aplicativo que estava em execução. Isso efetivamente cria um modelo de navegação em que o botão Voltar navega pelas páginas de um aplicativo em execução ou pela pilha de aplicativo anteriormente em execução.

APIs do Windows Phone

Como já observado, os principais agentes da navegação são PhoneApplicationFrame e PhoneApplicationPage.

PhoneApplicationFrame atua como RootVisual para o aplicativo. Na inicialização, um PhoneApplicationFrame é instanciado na classe App em App.xaml.cs (veja a Figura 1).

Figura 1 Instanciação de RootFrame em App.xaml.cs

private void InitializePhoneApplication()
{
  if (phoneApplicationInitialized)
        return;

  // Create the frame but don't set it as RootVisual yet; this allows the splash
  // screen to remain active until the application is ready to render.
  RootFrame = new PhoneApplicationFrame();
  RootFrame.Navigated += CompleteInitializePhoneApplication;

           
  // Handle navigation failures
  RootFrame.NavigationFailed += RootFrame_NavigationFailed;

  // Ensure we don't initialize again
  phoneApplicationInitialized = true;
}

O tempo de execução automaticamente navega até a instância de PhoneApplicationPage, que é especificada pelo atributo NavigationPage em DefaultTask no manifesto de aplicativo WMAppManifest.xml, como mostrado aqui:

<Tasks>
  <DefaultTask  Name ="_default" NavigationPage="MainPage.xaml"/> 
</Tasks>

Falando sobre responsabilidades e APIs mais detalhadamente, PhoneApplicationFrame expõe a maioria dos eventos e métodos de navegação dos quais precisaremos neste artigo. A Figura 2 lista os métodos, propriedades e eventos mais relevantes de PhoneApplicationFrame.

Figura 2 Métodos, propriedades e eventos de PhoneApplicationFrame

Nome Tipo Descrição
Navigate Método Navega até um novo PhoneApplicationPage especificado pelo parâmetro URI. O parâmetro é um Uri, por isso uma chamada a Navigate efetivamente instancia a nova página e navega até ela (você não o passa em uma página já instanciada).
CanGoBack Propriedade somente leitura Retorna true se a pilha voltar do aplicativo (o histórico do registro em diário) não está vazia. Isso significa que os usuários fizeram navegação progressiva pelo menos uma vez no aplicativo. Se o aplicativo estiver na primeira página carregada no aplicativo, CanGoBack retornará false e você não poderá chamar GoBack por programação, mas o usuário final ainda poderá pressionar o botão Voltar do hardware e o aplicativo sairá porque está voltando ao aplicativo que estava em execução.
CanGoForward Propriedade somente leitura Não aplicável ao Windows Phone. Sempre retorna false porque não há suporte para navegação progressiva.
UriMapper Propriedade Obtém/define um UriMapper. Está além do escopo deste artigo, mas vale mencionar que há suporte para o mapeamento de Uri.
GoBack Método Navega até a entrada mais recente na pilha voltar. Este método emitirá uma exceção se não houver nenhuma entrada na pilha voltar; sempre verifique CanGoForward antes de chamar este método.
GoForward Método Sem suporte no Windows Phone; emitirá InvalidOperationException
Navigating Evento Ocorre quando é solicitada uma nova navegação. Neste momento, ainda é possível cancelá-lo; para isso, defina a propriedade Cancel no parâmetro NavigatingCancelEventArgs como true. Consulte mais adiante as observações sobre por que você não deve cancelar navegações regressivas neste evento.
Navigated Evento Ocorre quando uma navegação foi executada. Isso não significa que o conteúdo da página navegada foi carregado. Ele simplesmente ocorre quando o conteúdo foi localizado e acessado.
NavigationFailed Evento Ocorre quando um erro é encontrado.
NavigationStopped Evento Ocorre quando a navegação é interrompida chamando o método StopLoading ou mais comumente quando uma nova navegação é solicitada e uma navegação estava em andamento.

A maioria deles é herdada de Frame, por isso, para quem já conhece a classe Frame do Silverlight, esses métodos devem parecer familiares. A lista exibida na Figura 2 não inclui todos os recursos de PhoneApplicationFrame, apenas os relevantes para navegação.

Código passo a passo: para ver todos esses eventos e propriedades em ação, explore AllNavigationsEvents.xaml.cs no código de exemplo que acompanha este artigo. Você também pode ver a ordem em que os eventos são disparados na Figura 3.

image: ng>The Sequence of Events as You Navigate Across Pages

Figura 3 A sequência de eventos à medida que você navega por páginas

PhoneApplicationFrame também determina a área de cliente que o aplicativo terá e reserva o espaço para a barra de aplicativo e a bandeja do sistema. Esse detalhe será relevante à medida que navegamos por páginas que têm uma barra de aplicativo, porque ela é especificada no nível de página e há uma animação no sistema inteiro que mostra e oculta a barra de aplicativo conforme as páginas são carregadas.

O segundo participante da navegação é PhoneApplicationPage. Ele desempenha dois papéis cruciais na navegação:

  • Manipular os pressionamentos do botão Voltar do hardware.
  • Fornecer eventos de ciclo de vida de página que permitem saber quando uma página é ativada/desativada.

Para integração com o botão Voltar do hardware, PhoneApplicationPage expõe um evento BackKeyPress. A página também tem um método OnBackKeyPress virtual que você pode substituir na instância de uma página para manipular e até mesmo cancelar um evento de pressionamento do botão Voltar.

PhoneApplicationFrame tem um evento Navigating e uma notificação/retorno de chamada OnNavigatingFrom. Em ambos, é possível cancelar navegações para outras páginas de dentro do aplicativo definindo e.Cancel = true no parâmetro NavigationCancelEventArgs passado para esses métodos; devido a um bug conhecido na plataforma, você não deve cancelar navegações com o botão Voltar usando esses eventos/métodos. Se você cancelar um pressionamento do botão Voltar do hardware nesse evento, a navegação será interrompida e o aplicativo deverá ser reiniciado. Os dois únicos métodos recomendados para cancelar um pressionamento do botão Voltar do hardware são o evento PhoneApplicationPage BackKeyPress e o retorno de chamada OnBackKeyPress.

Veja na Figura 4 uma lista de eventos e métodos em que é possível cancelar navegações, com recomendações sobre se é possível cancelar um pressionamento do botão Voltar no método em questão e uma orientação sobre como verificar se o evento era uma navegação regressiva.

Figura 4 Eventos e métodos em que é possível cancelar navegações

Proprietário Evento/notificação Pode cancelar uma nova navegação Pode cancelar navegações regressivas Verificar se há navegações regressivas
PhoneApplicationFrame Navigating Sim Não Sim; verificar e.NavigationMode != NavigationMode.Back
PhoneApplicationPage OnNavigatingFrom Sim Não Sim; verificar e.NavigationMode != NavigationMode.Back
PhoneApplicationPage OnBackKeyPress Não (chamado somente quando o pressionamento da tecla Voltar é chamado) Sim Não necessário; chamado somente em pressionamentos da tecla Voltar do hardware
PhoneApplicationPage BackKeyPress (evento) Não (chamado somente quando o pressionamento da tecla Voltar é chamado) Sim Não necessário; chamado somente em pressionamentos da tecla Voltar do hardware

PhoneApplicationPage complementa esses eventos para completar o ciclo de vida da navegação com as chamadas de retorno dos métodos OnNavigatedTo e OnNavigatedFrom mais úteis para a página. Para entender melhor e lembrar facilmente quando esses retornos de chamada são chamados, é recomendável completar os nomes de método com o texto “esta página”. Um método é chamado quando o usuário “navega até esta página” e, posteriormente, o outro método é chamado quando o usuário “navega desta página” para outra.

A Figura 3 mostra a sequência de eventos conforme você navega entre páginas. A simetria entre NavigatedTo/NavigatedFrom torna esses dois métodos ideais para iniciar e interromper um trabalho que é necessário quando a página está visível, mas não é necessário quando ela está na pilha voltar. Observe também que NavigatedTo sempre é disparado quando uma página é carregada, por isso não presuma que o conteúdo da página seja carregado nesse momento.

O motivo pelo qual OnNavigatedTo e OnNavigatedFrom são cruciais para o Windows Phone é por causa da pilha voltar. O sistema operacional mantém a pilha voltar para páginas às quais você pode retornar, assim as páginas não são imediatamente descarregadas, destruídas ou coletadas como lixo quando ocorre navegação de uma página para outra. Em vez disso, as páginas são movidas para a pilha voltar e mantidas ativas (na memória) e, quando o usuário clica em voltar para acessar a página em questão, ela é simplesmente adicionada de volta na árvore visual. A página não é recriada (a menos que o aplicativo tenha sido desativado e marcado para exclusão entre o momento em que o usuário saiu da página e clicou em voltar). Como não há suporte para diário progressivo, as páginas estão qualificadas para coleta como lixo quando você navega de uma página de volta à anterior, presumindo que não haja outras referências a essa página.

A Figura 5 mostra um diagrama que ilustra o ciclo de vida de PhoneApplicationPage.

image: The PhoneApplicationPage Lifecycle

Figura 5 O ciclo de vida de PhoneApplicationPage

À medida que você navega de Page1 para Page2 e, depois, para Page3, as páginas não são coletadas como lixo até o método GoBack da página ser chamado. As páginas inativas estão na pilha voltar, mas ainda permanecem na memória. Se elas estiverem detectando eventos globais, os ouvintes de evento ainda estarão ativos.

Apesar de não ser coletada como lixo quando você sai dela, uma página não fica mais visível ou ativa até você retornar, portanto você deve fazer qualquer limpeza e liberar quaisquer recursos caros quando o usuário sair de uma página. Por exemplo, se estiver detectando alterações de local com GeoCoordinateWatcher, você deverá interromper o ouvinte em OnNavigatedFrom e reiniciá-lo quando o usuário voltar à página – e o método OnNavigatedTo da página será chamado.

Código passo a passo: Para ver como as páginas são mantidas na memória enquanto estão na pilha voltar, explore a página GarbageCollectedSample incluída no código para download que acompanha este artigo. Ela mantém uma contagem cumulativa de páginas na memória, e você pode vê-la aumentar conforme avança na navegação ou diminuir quando navega de volta de uma página.

Isso encerra a primeira parte da nossa série. No mês que vem, vamos nos concentrar em tópicos de navegação avançada.

Yochay Kiriaty é especialista técnico sênior da Microsoft, especializado em tecnologias de cliente, como Windows e Windows Phone. É coautor dos livros “Introducing Windows 7 for Developers” (Microsoft Press, 2009) e “Learning Windows Phone Programming” (O’Reilly Media, 2011).

Jaime Rodriguez é um dos principais especialistas da Microsoft e orienta na adoção de tecnologias de cliente emergentes, como Silverlight e Windows Phone. Você pode contatá-lo pelo Twitter: @jaimerodriguez ou no endereço blogs.msdn.com/jaimer.

Agradecemos ao seguinte especialista técnico pela revisão deste artigo: Peter Torr