Um gráfico de navegação pode consistir em qualquer combinação dos itens a seguir:
- Um destino só, como
<fragment>
. - Um gráfico aninhado que encapsula um conjunto de destinos relacionados.
- Um elemento
<include>
, que permite incorporar outro arquivo de gráfico de navegação como se ele estivesse aninhado.
Essa flexibilidade permite combinar gráficos de navegação menores para formar o gráfico de navegação completo do app, mesmo que esses gráficos menores sejam fornecidos por módulos separados.
Para os exemplos deste tópico, cada
módulo de recursos será focado
em torno de um recurso e
fornece um único gráfico de navegação que encapsula todos os destinos
necessárias para implementar esse recurso. Em um app de produção, você pode ter muitos
submódulos em um nível mais baixo, que são detalhes de implementação do módulo de recursos de
nível mais alto. Cada um desses módulos é incluído, direta ou
indiretamente, no
módulo do app
. O aplicativo
de exemplo com vários módulos usado neste documento tem
esta estrutura:
Cada módulo de recursos é uma unidade independente com um gráfico de navegação
e destinos próprios. O módulo app
depende deles, adicionando-os como
detalhes de implementação no arquivo build.gradle
, conforme mostrado abaixo:
Groovy
dependencies { ... implementation project(":feature:home") implementation project(":feature:favorites") implementation project(":feature:settings")
Kotlin
dependencies { ... implementation(project(":feature:home")) implementation(project(":feature:favorites")) implementation(project(":feature:settings"))
O papel do módulo app
O módulo do app
é responsável por fornecer o gráfico completo do
app e adicionar o NavHost
à IU. No gráfico de navegação do módulo do
app
, você pode referenciar os gráficos da biblioteca usando
<include>
. Embora
o uso de <include>
seja funcionalmente o mesmo que o uso de um gráfico aninhado,
<include>
oferece suporte a gráficos de outros módulos do projeto ou de projetos de
biblioteca, como mostrado no exemplo abaixo:
<?xml version="1.0" encoding="utf-8"?>
<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"
android:id="@+id/nav_graph"
app:startDestination="@id/home_nav_graph">
<include app:graph="@navigation/home_navigation" />
<include app:graph="@navigation/favorites_navigation" />
<include app:graph="@navigation/settings_navigation" />
</navigation>
Quando uma biblioteca for incluída no gráfico de navegação de nível superior, vai ser possível navegar pelos gráficos da biblioteca conforme necessário. Por exemplo, você pode criar uma ação para navegar até o gráfico de configurações de um fragmento no gráfico de navegação, conforme mostrado abaixo:
<?xml version="1.0" encoding="utf-8"?>
<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"
android:id="@+id/nav_graph"
app:startDestination="@id/home_nav_graph">
<include app:graph="@navigation/home_navigation" />
<include app:graph="@navigation/favorites_navigation" />
<include app:graph="@navigation/settings_navigation" />
<fragment
android:id="@+id/random_fragment"
android:name="com.example.android.RandomFragment"
android:label="@string/fragment_random" >
<!-- Launch into Settings Navigation Graph -->
<action
android:id="@+id/action_random_fragment_to_settings_nav_graph"
app:destination="@id/settings_nav_graph" />
</fragment>
</navigation>
Quando vários módulos de biblioteca precisam referenciar um conjunto comum de
destinos, como um gráfico de login, não é possível incluir esses
destinos comuns no gráfico de navegação de cada módulo de recursos. Em vez disso,
adicione esses destinos comuns ao gráfico de navegação do módulo app
.
Dessa forma, cada módulo de recursos pode navegar pelos módulos
para ir até esses destinos comuns.
No exemplo anterior, a ação especifica um destino de navegação
de @id/settings_nav_graph
. Esse ID se refere a um destino
definido no gráfico incluído @navigation/settings_navigation.
Navegação de nível superior no módulo do app
O componente de navegação inclui uma classe
NavigationUI
.
Essa classe contém métodos estáticos que gerenciam a navegação com a barra
de apps de cima, a gaveta de navegação e a navegação inferior. Se os destinos
de nível mais alto do app forem compostos por elementos da IU fornecidos por módulos
de recursos, o módulo app
vai ser um lugar natural para colocar os elementos da IU e
a navegação de nível mais alto. Como o módulo do app depende dos
módulos de recursos colaborativos, todos os destinos são acessíveis
no código definido no módulo do app. Isso significa que você pode usar a
NavigationUI
para
associar destinos a itens de menu
quando o ID do item corresponde ao ID de um destino.
Na figura 2, o módulo app
de exemplo define uma
BottomNavigationView
na atividade principal. Os IDs de item de menu correspondem aos IDs dos gráficos de navegação
da biblioteca:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@id/home_nav_graph"
android:icon="@drawable/ic_home"
android:title="Home"
app:showAsAction="ifRoom"/>
<item
android:id="@id/favorites_nav_graph"
android:icon="@drawable/ic_favorite"
android:title="Favorites"
app:showAsAction="ifRoom"/>
<item
android:id="@id/settings_nav_graph"
android:icon="@drawable/ic_settings"
android:title="Settings"
app:showAsAction="ifRoom" />
</menu>
Para permitir que NavigationUI
gerencie a
navegação inferior, chame
setupWithNavController()
em onCreate()
na sua classe de atividade principal, conforme mostrado no
exemplo a seguir:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment val navController = navHostFragment.navController findViewById<BottomNavigationView>(R.id.bottom_nav) .setupWithNavController(navController) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); NavHostFragment navHostFragment = (NavHostFragment) supportFragmentManager.findFragmentById(R.id.nav_host_fragment); NavController navController = navHostFragment.getNavController(); BottomNavigationView bottomNav = findViewById(R.id.bottom_nav); NavigationUI.setupWithNavController(bottomNav, navController); }
Com esse código, a NavigationUI
vai navegar até o gráfico de
biblioteca adequado quando o usuário clicar em um item de navegação inferior.
Geralmente, não é recomendado o módulo do app ter uma dependência forte de um destino específico incorporado de forma profunda ao gráfico de navegação dos módulos de recursos. Na maioria dos casos, convém que o módulo do app saiba apenas sobre o ponto de entrada de todos os gráficos de navegação incorporados ou incluídos. Isso também se aplica fora de módulos de recursos. Se você precisar criar um link para um destino profundo no gráfico de navegação da biblioteca, a maneira preferencial de fazer isso é usando um link direto. Links diretos também são a única maneira de uma biblioteca navegar para um destino no gráfico de navegação de outra biblioteca.
Como navegar por módulos de recursos
Durante a compilação, os módulos de recursos independentes não podem acessar uns aos outros, então não é possível usar IDs para navegar para destinos em outros módulos. Em vez disso, use um link direto para navegar diretamente até um destino associado a um link direto implícito.
Continuando com o exemplo anterior, imagine que você precisa navegar de um botão no
módulo :feature:home
até um destino aninhado no módulo
:feature:settings
. Para fazer isso, adicione um link direto para o destino no gráfico de navegação
das configurações, conforme mostrado abaixo:
<?xml version="1.0" encoding="utf-8"?>
<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"
android:id="@+id/settings_nav_graph"
app:startDestination="@id/settings_fragment_one">
...
<fragment
android:id="@+id/settings_fragment_two"
android:name="com.example.google.login.SettingsFragmentTwo"
android:label="@string/settings_fragment_two" >
<deepLink
app:uri="android-app://example.google.app/settings_fragment_two" />
</fragment>
</navigation>
Depois, adicione o código abaixo ao onClickListener
do botão no fragmento
de início:
Kotlin
button.setOnClickListener { val request = NavDeepLinkRequest.Builder .fromUri("android-app://example.google.app/settings_fragment_two".toUri()) .build() findNavController().navigate(request) }
Java
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { NavDeepLinkRequest request = NavDeepLinkRequest.Builder .fromUri(Uri.parse("android-app://example.google.app/settings_fragment_two")) .build(); NavHostFragment.findNavController(this).navigate(request); } });
Diferentemente da navegação usando IDs de ação ou de destino, você pode navegar para qualquer URI em qualquer gráfico, mesmo entre módulos.
Ao navegar usando URI, a backstack não é redefinida. Esse comportamento é diferente de outras navegações de link direto explícito, em que a backstack é substituída durante a navegação.