Wykres nawigacyjny może składać się z dowolnej kombinacji następujących elementów:
- Pojedyncze miejsce docelowe, np.
<fragment>
. - Zagnieżdżony wykres obejmujący zbiór powiązanych miejsc docelowych.
- Element
<include>
, który umożliwia umieszczenie innego pliku wykresu nawigacyjnego, jak gdyby był on zagnieżdżony.
Ta elastyczność pozwala łączyć mniejsze wykresy nawigacyjne, aby utworzyć pełny wykres nawigacyjny aplikacji, nawet jeśli te mniejsze wykresy nawigacyjne są wyposażone w osobne moduły.
.W przypadku przykładów z tego tematu każdy moduł funkcji skupia się na 1 funkcji i zawiera jeden wykres nawigacyjny obejmujący wszystkie miejsca docelowe potrzebne do implementacji tej funkcji. W aplikacji produkcyjnej może znajdować się wiele modułów podrzędnych na niższym poziomie, które zawierają szczegóły implementacji modułu funkcji wyższego poziomu. Każdy z tych modułów funkcji jest uwzględniany (bezpośrednio lub pośrednio) w module app
. Przykładowa aplikacja składająca się z wielu modułów użyta w tym dokumencie ma taką strukturę:
Każdy moduł funkcji jest samodzielną jednostką z własnym wykresem nawigacyjnym i miejscami docelowymi. Moduł app
zależy od każdego z nich i dodaje je jako szczegóły implementacji w pliku build.gradle
, jak na przykładzie:
Odlotowy
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"))
Rola modułu app
Moduł app
odpowiada za pokazanie pełnego wykresu Twojej aplikacji i dodanie do interfejsu NavHost
modułu. Na wykresie nawigacyjnym w module app
możesz odwoływać się do wykresów bibliotecznych za pomocą funkcji <include>
. Chociaż funkcja <include>
działa tak samo jak graf zagnieżdżony, <include>
obsługuje wykresy z innych modułów projektu lub projektów bibliotecznych, jak w tym przykładzie:
<?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>
W razie potrzeby po dodaniu biblioteki do wykresu nawigacyjnego najwyższego poziomu możesz przejść do niego. W ten sposób możesz np. przejść do wykresu ustawień z fragmentu wykresu nawigacyjnego:
<?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>
Jeśli wiele modułów funkcji musi odwoływać się do wspólnego zestawu miejsc docelowych, np. do wykresu logowania, nie należy dodawać tych popularnych miejsc docelowych do wykresu nawigacji każdego modułu funkcji. Zamiast tego dodaj te wspólne miejsca docelowe do wykresu nawigacyjnego w module app
.
Każdy moduł funkcji może następnie przechodzić między modułami funkcji, aby przechodzić do tych typowych miejsc docelowych.
W poprzednim przykładzie działanie wskazuje miejsce docelowe nawigacji @id/settings_nav_graph
. Ten identyfikator odnosi się do miejsca docelowego określonego na uwzględnionym wykresie @navigation/settings_navigation.
Nawigacja najwyższego poziomu w module aplikacji
Komponent Nawigacja zawiera klasę NavigationUI
.
Ta klasa zawiera metody statyczne zarządzające nawigacją za pomocą górnego paska aplikacji, panelu nawigacji i dolnego obszaru nawigacyjnego. Jeśli miejsca docelowe najwyższego poziomu aplikacji składają się z elementów interfejsu dostarczanych przez moduły funkcji, moduł app
jest naturalnym miejscem, w którym można umieścić elementy nawigacyjne i elementy interfejsu najwyższego poziomu. Moduł aplikacji wymaga współpracy modułów funkcji, więc wszystkie ich miejsca docelowe są dostępne z poziomu kodu zdefiniowanego w module aplikacji. Oznacza to, że za pomocą polecenia NavigationUI
możesz wiązać miejsca docelowe z pozycjami menu, jeśli identyfikator elementu jest taki sam jak identyfikator miejsca docelowego.
Na rysunku 2 przykładowy moduł app
określa element BottomNavigationView
w swojej głównej aktywności. Identyfikatory pozycji menu w menu odpowiadają identyfikatorom wykresów nawigacyjnych na wykresach bibliotecznych:
<?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>
Aby umożliwić NavigationUI
obsługę dolnego nawigacji, wywołaj setupWithNavController()
z onCreate()
w głównej klasie aktywności, jak pokazano w tym przykładzie:
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); }
Gdy użytkownik kliknie ten element nawigacyjny, NavigationUI
przejdzie do odpowiedniego wykresu biblioteki.
Pamiętaj, że w przypadku modułu aplikacji głęboko zależność od konkretnego miejsca docelowego umieszczonego głęboko w wykresie nawigacji modułów funkcji jest ogólnie niewskazaną praktyką. Najczęściej moduł aplikacji powinien znać tylko punkt wejścia do umieszczonych lub dołączonych wykresów nawigacyjnych (dotyczy to również poza modułami funkcji). Jeśli chcesz dodać link do miejsca docelowego umieszczony głębiej na wykresie nawigacyjnym biblioteki, najlepiej użyć precyzyjnego linku. Precyzyjne linki są też jedynym sposobem przejścia biblioteki do miejsca docelowego na wykresie nawigacyjnym innej biblioteki.
Przechodzenie między modułami funkcji
W czasie kompilacji niezależne moduły funkcji nie widzą się nawzajem, więc nie możesz używać identyfikatorów do przechodzenia do miejsc docelowych w innych modułach. Zamiast tego użyj precyzyjnego linku, aby przejść bezpośrednio do miejsca docelowego powiązanego z ukrytym precyzyjnym linkiem.
Kontynuując poprzedni przykład, załóżmy, że musisz przejść z przycisku w module :feature:home
do miejsca docelowego umieszczonego w module :feature:settings
. Możesz to zrobić, dodając precyzyjny link do miejsca docelowego na wykresie nawigacyjnym ustawień, jak pokazano poniżej:
<?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>
Następnie dodaj następujący kod do sekcji onClickListener
przycisku we fragmencie głównym:
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); } });
W przeciwieństwie do nawigacji przy użyciu identyfikatorów działań lub miejsc docelowych możesz przejść do dowolnego identyfikatora URI na dowolnym wykresie, a nawet w obrębie modułów.
Podczas nawigowania za pomocą identyfikatora URI stos wsteczny nie jest resetowany. W przeciwieństwie do bezpośredniej nawigacji po precyzyjnych linkach, gdzie podczas nawigowania stos tylny jest zastępowany.