O componente de arquitetura de navegação simplifica a implementação da navegação e ajuda a visualizar o fluxo dela no seu app. A biblioteca oferece diversos benefícios, incluindo:
- Processamento automático de transações de fragmentos
- Processamento correto de Para cima e Voltar por padrão
- Comportamento padrão para animações e transições
- Links diretos como uma operação diferenciada
- Implementação de padrões de IU de navegação (como gavetas de navegação e navegação inferior) com pouco trabalho extra
- Segurança de tipo ao transmitir informações durante a navegação
- Ferramentas do Android Studio para visualizar e editar o fluxo de navegação de um app
Pré-requisitos
Neste codelab, você trabalhará com o app de exemplo abaixo:
Todos os fragmentos e atividades já foram criados para você. Você usará o componente de navegação para conectá-los. Ao fazer isso, implemente o seguinte:
- Gráfico de navegação visual
- Navegação por destino e ação
- Animações de transição
- Navegação no menu, navegação na parte inferior e navegação na gaveta do menu
- Transmissão de argumento com segurança de tipo
- Links diretos
Pré-requisitos
- Conhecimento básico sobre Kotlin (este codelab está em Kotlin)
- Android Studio 3.2 ou versões mais recentes
- Emulador ou dispositivo com API 14 ou mais recente
Buscar o código
Clone o codelab de navegação do GitHub:
$ git clone https://github.com/googlecodelabs/android-navigation
Se preferir, faça o download do repositório como um arquivo ZIP:
Instalar o Android Studio 3.3 ou versões mais recentes
Verifique se você está usando o Android Studio 3.3 ou mais recente. Isso é necessário para as ferramentas de navegação do Android Studio.
Se for necessário fazer o download de uma versão recente do Android Studio, acesse aqui.
Visão geral da navegação
O componente de navegação consiste em três partes principais, que trabalham juntas em harmonia. São eles:
- Gráfico de navegação (novo recurso XML): este é um recurso que contém todas as informações relacionadas à navegação em um local centralizado. Isso inclui todos os locais do app, conhecidos como destinos, e os possíveis caminhos que um usuário pode seguir pelo seu app.
- NavHostFragment (visualização XML de layout): este é um widget especial que pode ser adicionado ao layout. Ele exibe destinos diferentes do seu gráfico de navegação.
- NavController (objeto Kotlin/Java): este é um objeto que rastreia a posição atual no gráfico de navegação. Ele orquestra a troca de conteúdo de destino no
NavHostFragment
à medida que você percorre um gráfico de navegação.
Quando você navegar, usará o objeto NavController, informando-o para onde quer ir ou qual caminho quer seguir no seu gráfico de navegação. O NavController
mostrará o destino adequado no NavHostFragment.
Essa é a ideia básica. Veja como isso funciona na prática, começando pelo novo recurso de gráfico de navegação.
Destinos
O componente de navegação introduz o conceito de destino. Um destino é qualquer local em que é possível navegar no app, geralmente um fragmento ou uma atividade. Eles são aceitos imediatamente, mas também é possível criar seus próprios tipos de destino personalizados, se necessário.
Gráfico de navegação
O gráfico de navegação é um novo tipo de recurso que define todos os caminhos possíveis que um usuário pode seguir em um app. Ela mostra visualmente todos os destinos que podem ser alcançados de determinado destino. O Android Studio exibe o gráfico no Navigation Editor. Veja o gráfico de navegação inicial que você criará para seu app:
Como explorar o Navigation Editor
1. Abra res/navigation/mobile_navigation.xml
.
2. Clique em Design para entrar no modo Design:
Você verá o seguinte:
O gráfico de navegação mostra os destinos disponíveis. As setas entre os destinos são chamadas ações. Você aprenderá mais sobre as ações depois.
3. Clique em um destino para ver os atributos dele.
4. Clique em qualquer ação, representada por uma seta, para ver os atributos dela.
Anatomia de um arquivo XML de navegação
Todas as mudanças feitas no Navigation Editor gráfico mudam o arquivo XML subjacente, de forma semelhante à que o Layout Editor modifica o XML do layout.
Clique na guia Text:
Você verá um XML como este:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@+id/home_dest">
<!-- ...tags for fragments and activities here -->
</navigation>
Aviso:
- O
<navigation>
é o nó raiz de todos os gráficos de navegação. - O
<navigation>
contém um ou mais destinos, representados pelos elementos<activity>
ou<fragment>
. - O
app:startDestination
é um atributo que especifica o destino que é iniciado por padrão quando o usuário abre o app pela primeira vez.
Veja o destino de um fragmento:
<fragment
android:id="@+id/flow_step_one_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_one_fragment">
<argument
.../>
<action
android:id="@+id/next_action"
app:destination="@+id/flow_step_two_dest">
</action>
</fragment>
Aviso:
- O
android:id
define um ID para o fragmento que pode ser usado para referenciar o destino em outro lugar no XML e no seu código. - O
android:name
declara o nome da classe totalmente qualificada do fragmento a ser instanciado quando você navega para esse destino. - O
tools:layout
especifica qual layout deve ser exibido no editor gráfico.
Algumas tags <fragment>
também contêm <action>
, <argument>,
e <deepLink>
, que serão abordados mais adiante.
O app de exemplo começa com alguns destinos no gráfico. Nesta etapa, você adicionará um novo destino. É necessário adicionar um destino ao gráfico de navegação para poder navegar até ele.
1. Abra res/navigation/mobile_navigation.xml
e clique na guia Design.
2. Clique no ícone New Destination e selecione "settings_fragment".
O resultado é um novo destino, que renderiza uma visualização do layout do fragmento na visualização de design.
Também é possível editar o arquivo XML diretamente para adicionar destinos:
mobile_navigation.xml
<fragment
android:id="@+id/settings_dest"
android:name="com.example.android.codelabs.navigation.SettingsFragment"
android:label="@string/settings"
tools:layout="@layout/settings_fragment" />
No momento, você tem esse gráfico de navegação incrível, mas ele ainda não está sendo usando para navegar.
Atividades e navegação
O componente de navegação segue a orientação descrita nos Princípios de navegação. Esses princípios recomendam o uso de atividades como pontos de entrada para o app. As atividades também terão uma navegação global, como a navegação inferior.
Em comparação, os fragmentos serão os layouts reais específicos do destino.
Para que tudo isso funcione, é necessário modificar os layouts da atividade para que contenham um widget especial chamado NavHostFragment
. Um NavHostFragment
alterna diferentes destinos de fragmentos para dentro e para fora enquanto você navega no gráfico de navegação.
Um layout simples compatível com navegação semelhante à imagem acima tem a seguinte aparência. Veja um exemplo de código em res/layout-470dp/navigation_activity.xml
:
<LinearLayout
.../>
<androidx.appcompat.widget.Toolbar
.../>
<fragment
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/my_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/mobile_navigation"
app:defaultNavHost="true"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
.../>
</LinearLayout>
Aviso:
- Este é um layout para uma atividade. Ele contém a navegação global, incluindo uma navegação inferior e uma barra de ferramentas
android:name="androidx.navigation.fragment.NavHostFragment"
eapp:defaultNavHost="true"
conectam o botão "Voltar" do sistema aoNavHostFragment
app:navGraph="@navigation/mobile_navigation"
associa oNavHostFragment
a um gráfico de navegação. O gráfico de navegação especifica todos os destinos a que o usuário pode navegar nesseNavHostFragment
.
NavController
Por fim, quando um usuário faz algo como clicar em um botão, é preciso acionar um comando de navegação. Uma classe especial chamada NavController
é o que aciona as trocas de fragmento no NavHostFragment
.
// Command to navigate to flow_step_one_dest
findNavController().navigate(R.id.flow_step_one_dest)
Você precisa transmitir um ID de ação ou de destino para navegar. Esses são os IDs definidos no XML do gráfico de navegação. Esse é um exemplo de transmissão de ID de destino.
O NavController
é eficiente porque, quando você chama métodos como navigate()
ou popBackStack(),
, ele converte esses comandos nas operações de framework adequadas com base no tipo de destino para o qual você está navegando ou de onde está vindo. Por exemplo, quando você chama o navigate()
com um destino de atividade, o NavController
chama startActivity()
em seu nome.
Há algumas maneiras de associar um objeto NavController
ao seu NavHostFragment
. No Kotlin, é recomendável usar uma das seguintes funções de extensão, dependendo se você está chamando o comando de navegação em um fragmento, uma atividade ou uma visualização:
Navegar até um destino com NavController
É sua vez de navegar usando o NavController
. Você pressionará o botão Navigate To Destination para navegar até o destino flow_step_one_dest
, que é um FlowStepFragment
:
1. Abra HomeFragment.kt
.
2. Conecte navigate_destination_button
a onViewCreated()
.
HomeFragment.kt
val button = view.findViewById<Button>(R.id.navigate_destination_button)
button?.setOnClickListener {
findNavController().navigate(R.id.flow_step_one_dest, null)
}
3. Execute o app e clique no botão Navigate To Destination. O botão navega até o destino flow_step_one_dest
.
O código do listener de clique ficaria assim:
val button = view.findViewById<Button>(R.id.navigate_destination_button)
button?.setOnClickListener(
Navigation.createNavigateOnClickListener(R.id.flow_step_one_dest, null)
)
Cada chamada navigate()
tem uma transição padrão não muito animadora associada a ela, conforme mostrado abaixo:
A transição padrão, assim como outros atributos associados à chamada, pode ser modificada com a inclusão de um conjunto de NavOptions
. NavOptions
usa um padrão Builder
que permite substituir e configurar apenas as opções necessárias. Há também uma DSL ktx para NavOptions, que é a que você usará.
Para transições animadas, é possível definir recursos de animação XML na pasta de recursos anim
e usar essas animações para transições. Veja alguns exemplos no código do app:
Adicionar uma transição personalizada
Atualize o código para que, ao pressionar o botão Navigate To Destination, uma animação de transição personalizada seja exibida.
1. Abra HomeFragment.kt
.
2. Defina um NavOptions
e transmita-o para a chamada de navigate()
até navigate_destination_button
.
val options = navOptions {
anim {
enter = R.anim.slide_in_right
exit = R.anim.slide_out_left
popEnter = R.anim.slide_in_left
popExit = R.anim.slide_out_right
}
}
view.findViewById<Button>(R.id.navigate_destination_button)?.setOnClickListener {
findNavController().navigate(R.id.flow_step_one_dest, null, options)
}
3. Remova o código adicionado na etapa 5, se ainda estiver lá.
4. Verifique se, ao tocar no botão Navigate To Destination , o fragmento desliza para a tela e se, ao tocar em "Voltar", ele desliza para fora da tela.
Ações
O sistema de navegação também permite navegar por ações. Como mencionado anteriormente, as linhas mostradas no gráfico de navegação são representações visuais das ações.
A navegação por ações tem os seguintes benefícios sobre a navegação por destino:
- É possível ver os caminhos de navegação no seu app.
- As ações podem conter outros atributos associados que você pode configurar, como uma animação de transição, valores de argumentos e comportamento da pilha de retorno.
- Para navegar, é possível usar o plug-in Safe Args, que será exibido em breve.
Veja a aparência e XML da ação que conecta flow_step_one_dest
e flow_step_two_dest
:
<fragment
android:id="@+id/flow_step_one_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment">
<argument
.../>
<action
android:id="@+id/next_action"
app:destination="@+id/flow_step_two_dest">
</action>
</fragment>
<fragment
android:id="@+id/flow_step_two_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment">
<!-- ...removed for simplicity-->
</fragment>
Aviso:
- As ações estão aninhadas dentro do destino de onde você navegará.
- A ação inclui um argumento de destino que se refere a flow_step_two_dest. Esse é o ID para onde você navegará.
- O ID da ação é "next_action"
Veja outro exemplo da ação que conecta flow_step_two_dest
a home_dest
:
<fragment
android:id="@+id/home_dest"
android:name="com.example.android.codelabs.navigation.HomeFragment"
.../>
<fragment
android:id="@+id/flow_step_two_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment">
<argument
.../>
<action
android:id="@+id/next_action"
app:popUpTo="@id/home_dest">
</action>
</fragment>
Aviso:
- O mesmo ID next_action é usado para a ação que conecta
flow_step_two_dest
ahome_dest
. É possível navegar usando o ID next_action partindo deflow_step_one_dest
ouflow_step_two_dest
. Esse é um exemplo de como as ações podem fornecer um nível de abstração e podem navegar para outro lugar, dependendo do contexto. - O atributo
popUpTo
é usado. Essa ação remove os fragmentos da pilha de retorno até você chegar ahome_dest
.
Navegar com uma ação
É hora de conectar o botão Navigate with Action para que ele faça jus ao nome.
1. Abra o arquivo mobile_navigation.xml
no modo Design .
2. Arraste uma seta de home_dest
para flow_step_one_dest
:
3. Com a seta de ação selecionada (azul), mude as propriedades da ação para que:
- ID = next_action
- Transição para Enter = slide_in_right
- Transição para sair = slide_out_left
- Transição para Pop Enter = slide_in_left
- Transição para Pop Exit = slide_out_right
4. Clique na guia Text
Observe a ação next_action
adicionada recentemente no destino home_dest
:
mobile_navigation.xml
<fragment android:id="@+id/home_dest"
...>
<action android:id="@+id/next_action"
app:destination="@+id/flow_step_one"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
5. Abra HomeFragment.kt
.
6. Adicione um listener de clique ao navigate_action_button
.
HomeFragment.kt
view.findViewById<Button>(R.id.navigate_action_button)?.setOnClickListener(
Navigation.createNavigateOnClickListener(R.id.next_action, null)
)
7. Verifique se agora, ao tocar em Navigate To Action, você navega até a próxima tela.
Safe Args
O componente de navegação tem um plug-in para Gradle chamado Safe args que gera classes simples de objetos e builders para acesso com segurança de tipo a argumentos especificados para destinos e ações.
O Safe Args permite que você remova códigos como este ao transmitir valores entre destinos:
val username = arguments?.getString("usernameKey")
Em vez disso, substitua-o por um código que gerou setters e getters.
val username = args.username
Transmitir um valor usando o Safe Args
1. Abra o arquivo build.gradle
do projeto e observe o plug-in Safe Args:
build.gradle
dependencies {
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"
//...
}
2. Abra o arquivo app/build.gradle
e observe o plug-in aplicado:
app/build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'androidx.navigation.safeargs.kotlin'
android {
//...
}
3. Abra o mobile_navigation.xml,
e observe como os argumentos são definidos no destino flow_step_one_dest
.
mobile_navigation.xml
<fragment
android:id="@+id/flow_step_one_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_one_fragment">
<argument
android:name="flowStepNumber"
app:argType="integer"
android:defaultValue="1"/>
<action...>
</action>
</fragment>
Usando a tag <argument>
, o Safe Args gera uma classe chamada FlowStepFragmentArgs
.
Como o XML inclui um argumento chamado flowStepNumber
, especificado por android:name="flowStepNumber"
, a classe gerada FlowStepFragmentArgs
incluirá uma variável flowStepNumber
com getters e setters.
4. Abra FlowStepFragment.kt
.
5. Comente a linha de código mostrada abaixo:
FlowStepFragment.kt
// Comment out this line
// val flowStepNumber = arguments?.getInt("flowStepNumber")
Esse código antigo não tem segurança de tipo. É melhor usar o Safe Args.
6. Atualize o FlowStepFragment
para que use a classe FlowStepFragmentArgs
gerada pelo código. Isso receberá os argumentos FlowStepFragment
de maneira segura:
FlowStepFragment.kt
val safeArgs: FlowStepFragmentArgs by navArgs()
val flowStepNumber = safeArgs.flowStepNumber
Classes de rota do Safe Args
Também é possível usar o Safe Args para navegar de maneira segura, com ou sem a adição de argumentos. Faça isso usando as classes de rota geradas.
As classes de rotas são geradas para cada destino diferente com ações. A classe de rotas inclui métodos para todas as ações que um destino tem.
Por exemplo, o listener de clique navigate_action_button
em HomeFragment.kt pode ser alterado para:
HomeFragment.kt
// Note the usage of curly braces since we are defining the click listener lambda
view.findViewById<Button>(R.id.navigate_action_button)?.setOnClickListener {
val flowStepNumberArg = 1
val action = HomeFragmentDirections.nextAction(flowStepNumberArg)
findNavController().navigate(action)
}
NavigationUI e navigation-ui-ktx
Os componentes de Navigation incluem uma classe NavigationUI
e as extensões navigation-ui-ktx
do Kotlin. NavigationUI
tem métodos estáticos que associam itens de menu com destinos de navegação, e navigation-ui-ktx
é um conjunto de funções de extensão que também faz isso. Se a NavigationUI
encontra um item de menu com o mesmo ID de um destino no gráfico atual, ela configura o item de menu para navegar até esse destino.
Usar NavigationUI com um menu "Opções"
Uma das formas mais fáceis de usar a NavigationUI é simplificar a configuração do menu "opções". Em particular, a NavigationUI simplifica o gerenciamento do callback de onOptionsItemSelected
.
1. Abra MainActivity.kt.
Observe como você já possui o código para inflar o menu overflow_menu
em onCreateOptionsMenu
.
2. Abra res/menu/overflow_menu.xml
.
3. Atualize o menu flutuante para incluir o settings_dest
.
overflow_menu.xml
<item
android:id="@+id/settings_dest"
android:icon="@drawable/ic_settings"
android:menuCategory="secondary"
android:title="@string/settings" />
4. Abra MainActivity.kt
.
5. Faça com que NavigationUI gerencie onOptionsItemSelected
com o método auxiliar onNavDestinationSelected
. Caso o item do menu não seja destinado a navegação, use super.onOptionsItemSelected
.
MainActivity.kt
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return item.onNavDestinationSelected(findNavController(R.id.my_nav_host_fragment))
|| super.onOptionsItemSelected(item)
}
6. Execute o app. É preciso ter um menu funcional ActionBar que navegue até SettingsFragment.
Usar NavigationUI para configurar a navegação inferior
O código já contém o código de layout XML para implementar a navegação inferior. Por isso, você verá a barra de navegação inferior. Mas ele não navega para lugar nenhum.
1. Abra res/layout/navigation_activity/navigation_activity.xml (h470dp)
e clique na guia Texto.
Observe como o código de layout XML para navegação inferior está lá e se refere a bottom_nav_menu.xml
.
navigation_activity.xml (h470dp)
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_nav_menu" />
2. Abra res/menu/bottom_nav_menu.xml
.
Observe como há dois itens para a navegação inferior e que os IDs deles correspondem aos destinos do gráfico de navegação:
bottom_nav_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@id/home_dest"
android:icon="@drawable/ic_home"
android:title="@string/home" />
<item
android:id="@id/deeplink_dest"
android:icon="@drawable/ic_android"
android:title="@string/deeplink" />
</menu>
Vamos fazer a navegação inferior, de fato, fazer algo usando a NavigationUI.
3. Abra MainActivity.kt
.
4. Implemente o método setupBottomNavMenu
usando setupWithNavController(bottomNavigationView: BottomNavigationView, navController: NavController)
.
MainActivity.kt
private fun setupBottomNavMenu(navController: NavController) {
val bottomNav = findViewById<BottomNavigationView>(R.id.bottom_nav_view)
bottomNav?.setupWithNavController(navController)
}
Agora sua navegação inferior funciona!
Usar a NavigationUI para configurar uma gaveta de navegação
Por fim, vamos usar NavigationUI
para configurar a navegação lateral e a gaveta de navegação, incluindo o gerenciamento da ActionBar e da navegação superior adequada. Essa opção aparecerá se você tiver uma tela grande o suficiente ou se a tela for muito curta para a navegação inferior.
Primeiro, observe como o código XML de layout adequado já está no app.
1. Abra navigation_activity.xml
e navigation_activity.xml (w960dp)
.
Observe que os dois layouts contêm uma NavigationView conectada a nav_drawer_menu. Na versão para tablet (w960dp), a NavigationView fica sempre na tela. Em dispositivos menores, a NavigationView é aninhada em um DrawerLayout.
Para começar a implementar a navegação NavigationView
:
2. Abra MainActivity.kt
.
3. Implemente o método setupNavigationMenu
usando setupWithNavController(navigationView: NavigationView, navController: NavController)
. Observe como essa versão do método aceita uma NavigationView
, mas não uma BottomNavigationView
.
MainActivity.kt
private fun setupNavigationMenu(navController: NavController) {
val sideNavView = findViewById<NavigationView>(R.id.nav_view)
sideNavView?.setupWithNavController(navController)
}
Agora, o menu de visualização de navegação será exibido na tela, mas não afetará a ActionBar.
A configuração da ActionBar
requer a criação de uma instância de AppBarConfiguration
. O objetivo da AppBarConfiguration
é especificar as opções de configuração desejadas para suas barras de ferramentas, de recolhimento e de ações. As opções de configuração incluem se a barra precisa gerenciar um layout de gaveta e quais destinos são considerados destinos de nível superior.
Os destinos de nível superior são os destinos do nível raiz do seu app. Eles não exibem um botão "para cima" na barra de apps, e exibem o ícone de gaveta se o destino usa um layout de gaveta.
4. Crie um AppBarConfiguration
transmitindo um conjunto de IDs de destino de nível superior e o layout de gaveta.
MainActivity.kt
val drawerLayout : DrawerLayout? = findViewById(R.id.drawer_layout)
appBarConfiguration = AppBarConfiguration(
setOf(R.id.home_dest, R.id.deeplink_dest),
drawerLayout)
Agora que você tem uma AppBarConfiguration, pode chamar NavigationUI.setupActionBarWithNavController
. Isso fará o seguinte:
- Mostrará um título na ActionBar com base no rótulo do destino
- Exibirá o botão "Para cima" sempre que você não estiver em um destino de nível superior
- Exibirá um ícone de gaveta (ícone de hambúrguer) quando estiver em um destino de nível superior
5. Implemente o setupActionBarWithNavController
.
MainActivity.kt
private fun setupActionBar(navController: NavController,
appBarConfig : AppBarConfiguration) {
setupActionBarWithNavController(navController, appBarConfig)
}
Também é necessário que a NavigationUI gerencie o que acontece quando o botão "Para cima" é pressionado.
6. Modifique onSupportNavigationUp
e chame NavigationUI.navigateUp
usando a mesma AppBarConfiguration
.
MainActivity.kt
override fun onSupportNavigateUp(): Boolean {
return findNavController(R.id.my_nav_host_fragment).navigateUp(appBarConfiguration)
}
7. Execute o código. Se você abrir o app na tela dividida, é necessário ter uma gaveta de navegação funcionando. O ícone para cima e o ícone da gaveta devem ser exibidos nos momentos adequados e funcionar corretamente.
Adicionar novos destinos a uma NavigationView
é fácil. Quando a gaveta de navegação estiver funcionando com uma navegação para cima e para baixo, basta adicionar o novo item de menu.
8. Abra menu/nav_drawer_menu.xml
.
9. Adicione um novo item de menu a settings_dest
.
nav_drawer_menu.xml
<item
android:id="@+id/settings_dest"
android:icon="@drawable/ic_settings"
android:title="@string/settings" />
Agora, suas gavetas de navegação mostram a tela de configurações como um destino. Bom trabalho!
Links diretos e navegação
Os componentes de navegação também incluem compatibilidade com link direto. Links diretos são uma forma de ir para o meio da navegação do seu app, seja de um link de URL ou de uma intent pendente de uma notificação.
Uma vantagem de usar a biblioteca de navegação para gerenciar links diretos é garantir que os usuários comecem no destino certo com a pilha de retorno apropriada vinda de outros pontos de entrada, como widgets de apps, notificações ou links da Web (tratados na próxima etapa).
O Navigation oferece uma classe NavDeepLinkBuilder
para construir uma PendingIntent
que levará o usuário a um destino específico.
Adicionar um link direto
Usaremos o NavDeepLinkBuilder
para conectar um widget de app a um destino.
1. Abra DeepLinkAppWidgetProvider.kt
.
2. Adicione uma PendingIntent
construída com o NavDeepLinkBuilder
:
DeepLinkAppWidgetProvider
val args = Bundle()
args.putString("myarg", "From Widget");
val pendingIntent = NavDeepLinkBuilder(context)
.setGraph(R.navigation.mobile_navigation)
.setDestination(R.id.deeplink_dest)
.setArguments(args)
.createPendingIntent()
remoteViews.setOnClickPendingIntent(R.id.deep_link_button, pendingIntent)
Aviso:
- O
setGraph
inclui o gráfico de navegação. - O
setDestination
especifica para onde o link é direcionado. - O
setArguments
inclui todos os argumentos que você quer transmitir para o link direto.
3. Adicione o widget de link direto à tela inicial. Toque na tela inicial e mantenha-a pressionada para ver a opção de adicionar um widget.
Tocar e manter pressionado | Rolar para baixo para encontrar o widget |
Quando terminar, você terá um widget de link direto.
4. Toque no widget e verifique se o destino do Android abre com o argumento correto. A indicação "From Widget" aparece no topo, já que é o argumento que você transmitiu em DeepLinkAppWidgetProvider.
5. Verifique se pressionar o botão "Voltar" leva você ao destino do home_dest
.
Pilha de retorno de link direto
A pilha de retorno para um link direto é determinada usando o gráfico de navegação transmitido. Se a atividade explícita que você escolheu tiver uma atividade pai, essas atividades também serão incluídas.
A pilha de retorno é gerada usando os destinos especificados com app:startDestination
. Neste app, temos apenas uma atividade e um nível de navegação. Assim, a pilha de retorno levará você ao destino home_dest
.
A navegação mais complicada pode incluir gráficos de navegação aninhados. O app:startDestination
em cada nível dos gráficos aninhados determina a pilha de retorno. Para mais informações sobre links diretos e gráficos aninhados, confira os Princípios de navegação.
O elemento <deepLink>
Um dos usos mais comuns de um link direto é permitir que um link da Web abra uma atividade no seu app. Tradicionalmente, você usaria um filtro de intent e associaria um URL à atividade que quer abrir.
A biblioteca de navegação simplifica esse processo e permite mapear URLs diretamente para destinos no seu gráfico de navegação.
O <deepLink>
é um elemento que pode ser adicionado a um destino no gráfico. Cada elemento <deepLink>
tem um único atributo obrigatório: app:uri
.
Além da correspondência com URI direto, os seguintes recursos são compatíveis:
- Os URIs sem um esquema são considerados http e https. Por exemplo,
www.example.com
corresponderá ahttp://www.example.com
ehttps://www.example.com
. - É possível usar marcadores na forma de
{placeholder_name}
para corresponder a um ou mais caracteres. O valor de String do marcador está disponível no pacote de argumentos, que tem uma chave com o mesmo nome. Por exemplo,http://www.example.com/users/{id}
corresponderá ahttp://www.example.com/users/4
. - Você pode usar o caractere curinga
.*
para criar correspondência com zero ou mais caracteres. - O NavController gerenciará automaticamente as intents ACTION_VIEW e procurará links diretos correspondentes.
Adicionar um link direto baseado em URI usando <deepLink>
Nesta etapa, você adicionará um link direto a www.example.com.
1. Abra mobile_navigation.xml
.
2. Adicione um elemento <deepLink>
ao destino deeplink_dest
.
mobile_navigation.xml
<fragment
android:id="@+id/deeplink_dest"
android:name="com.example.android.codelabs.navigation.DeepLinkFragment"
android:label="@string/deeplink"
tools:layout="@layout/deeplink_fragment">
<argument
android:name="myarg"
android:defaultValue="Android!"/>
<deepLink app:uri="www.example.com/{myarg}" />
</fragment>
3. Abrir AndroidManifest.xml
4. Adicione a tag nav-graph
. Isso garantirá que o filtro de intent adequado seja gerado.
AndroidManifest.xml
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<nav-graph android:value="@navigation/mobile_navigation" />
</activity>
5. Inicie o app usando um link direto. Há duas maneiras de fazer isso:
- Use
adb
:
adb shell am start -a android.intent.action.VIEW -d "http://www.example.com/urlTest"
- Navegue pelo Google app É possível colocar www.example.com/urlTest na barra de pesquisa, e a janela de desambiguação será exibida. Selecione Codelab de navegação.
Abrir usando a barra de pesquisa (não no Chrome) | Caixa de diálogo de desambiguação |
De qualquer forma, a mensagem "urlTest" aparecerá na tela. Isso foi transmitido do URL para o fragmento.
Há mais uma parte do app do codelab para você testar: o botão de carrinho de compras.
Este é um resumo das habilidades que você aprendeu durante este codelab. Esta etapa não inclui comentários, então experimente por conta própria:
- Crie uma nova classe de fragmento.
- Adicione o fragmento como um destino ao gráfico de navegação.
- Faça o ícone do carrinho de compras abrir sua nova classe de fragmento, usando NavigationUI para gerenciar o menu.
Você já conhece os conceitos básicos do componente de navegação. Neste codelab, você aprendeu sobre:
- Estrutura do gráfico de navegação
- NavHostFragment e NavController
- Como navegar para destinos específicos
- Como navegar por ação
- Como transmitir argumentos entre destinos, incluindo o uso do novo plug-in Safe Args
- Como navegar usando menus, navegação inferior e gavetas de navegação
- Como navegar pelo link direto
Você pode continuar explorando esse app ou começar a usar a navegação no seu app.
Há muito mais para testar, como:
- Retirar destinos da pilha de retorno (ou qualquer manipulação de pilha de retorno)
- Gráficos de navegação aninhados
- Navegação condicional
- Adição de compatibilidade com novos destinos
Para saber mais sobre o componente de navegação, confira a documentação. Se você tem interesse em conhecer outros componentes de arquitetura, consulte os seguintes codelabs:
- Codelab Room com uma visualização (LiveData, ViewModel e Room)
- Codelab do Android WorkManager
- Codelab do Android Paging
- Codelab de componentes compatíveis com ciclo de vida do Android (LiveData e ViewModel)
- Codelab de persistência do Android (Room)