Procesy logowania, kreatory lub inne podprocesy w aplikacji najlepiej przedstawiać jako zagnieżdżone wykresy nawigacji. Dzięki zagnieżdżaniu zamkniętych podprzepływów nawigacji główny interfejs użytkownika aplikacji jest łatwiejszy do zrozumienia i zarządzania.
Dodatkowo można ponownie używać zagnieżdżonych wykresów. Zapewniają też pewien poziom enkapsulacji – miejsca docelowe spoza zagnieżdżonego grafu nie mają bezpośredniego dostępu do żadnych miejsc docelowych w zagnieżdżonym graficie. Zamiast tego należy użyć funkcji navigate()
do samego zagnieżdżonego wykresu, gdzie logika wewnętrzna może się zmieniać bez wpływu na pozostałą część wykresu.
Przykład
Główny diagram nawigacji w aplikacji powinien zaczynać się od początkowego miejsca docelowego, które użytkownik widzi po uruchomieniu aplikacji, i obejmować miejsca docelowe, które widzi podczas poruszania się po aplikacji.

Na przykładzie grafu nawigacji najwyższego poziomu na rysunku 1 załóżmy, że chcesz, aby użytkownik widział ekrany title_screen i register tylko wtedy, gdy aplikacja jest uruchamiana po raz pierwszy. Następnie informacje o użytkowniku są przechowywane, a przy kolejnych uruchamieniach aplikacji użytkownik powinien od razu przejść do ekranu dopasowania.
Zalecamy, aby ekran poszukiwania ustawić jako punkt początkowy w wykresie nawigacji najwyższego poziomu, a ekrany z tytułami i rejestracją przenieść do zagnieżdżonego wykresu, jak pokazano na rysunku 1:

Gdy pojawi się ekran dopasowania, sprawdź, czy jest zarejestrowany użytkownik. Jeśli użytkownik nie jest zarejestrowany, przekieruj go do ekranu rejestracji.
Więcej informacji o scenariuszach nawigacji warunkowej znajdziesz w artykule Nawigacja warunkowa.
Compose
Aby utworzyć zagnieżdżony graf nawigacji za pomocą Compose, użyj funkcji NavGraphBuilder.navigation()
. Podczas dodawania miejsc docelowych do grafu możesz używać funkcji navigation()
tak samo jak funkcji NavGraphBuilder.composable()
i NavGraphBuilder.dialog()
.
Główna różnica polega na tym, że navigation
tworzy zagnieżdżoną grafę, a nie nowe miejsce docelowe. Następnie w ramach funkcji lambda usługi navigation()
wywołujesz funkcje composable()
i dialog()
, aby dodać miejsca docelowe do grafu zagnieżdżonego.
Zwróć uwagę, jak ten fragment kodu tworzy wykres na rysunku 2 za pomocą usługi Compose:
// Routes
@Serializable object Title
@Serializable object Register
// Route for nested graph
@Serializable object Game
// Routes inside nested graph
@Serializable object Match
@Serializable object InGame
@Serializable object ResultsWinner
@Serializable object GameOver
NavHost(navController, startDestination = Title) {
composable<Title> {
TitleScreen(
onPlayClicked = { navController.navigate(route = Register) },
onLeaderboardsClicked = { /* Navigate to leaderboards */ }
)
}
composable<Register> {
RegisterScreen(
onSignUpComplete = { navController.navigate(route = Game) }
)
}
navigation<Game>(startDestination = Match) {
composable<Match> {
MatchScreen(
onStartGame = { navController.navigate(route = InGame) }
)
}
composable<InGame> {
InGameScreen(
onGameWin = { navController.navigate(route = ResultsWinner) },
onGameLose = { navController.navigate(route = GameOver) }
)
}
composable<ResultsWinner> {
ResultsWinnerScreen(
onNextMatchClicked = {
navController.navigate(route = Match) {
popUpTo(route = Match) { inclusive = true }
}
},
onLeaderboardsClicked = { /* Navigate to leaderboards */ }
)
}
composable<GameOver> {
GameOverScreen(
onTryAgainClicked = {
navController.navigate(route = Match) {
popUpTo(route = Match) { inclusive = true }
}
}
)
}
}
}
Aby przejść bezpośrednio do zagnieżdżonego miejsca docelowego, użyj typu trasy tak jak w przypadku dowolnego innego miejsca docelowego. Dzieje się tak, ponieważ trasy to globalna koncepcja służąca do identyfikowania miejsc docelowych, do których można przejść z dowolnego ekranu:
navController.navigate(route = Match)
XML
Jeśli używasz pliku XML, możesz utworzyć zagnieżdżony wykres za pomocą Edytora nawigacji. Aby to zrobić:
- W Edytorze nawigacji przytrzymaj klawisz Shift i kliknij miejsca docelowe, które chcesz uwzględnić w zagnieżdżonym wykresie.
Kliknij prawym przyciskiem myszy, aby otworzyć menu kontekstowe, i wybierz Przenieś do zagnieżdżonego wykresu > Nowy wykres. Miejsca docelowe są zamknięte w zagnieżdżonym wykresie. Rysunek 2. przedstawia zagnieżdżony wykres w Edytorze nawigacji:
Rysunek 2. Grafika zagnieżdżona w Edytorze nawigacji Kliknij graf zagnieżdżony. W panelu Atrybuty pojawiają się te atrybuty:
- Typ, który zawiera „Grafikę zagnieżdżoną”.
- Identyfikator, który zawiera przypisany przez system identyfikator grafu zagnieżdżonego. Ten identyfikator służy do odwoływania się w kodzie do grafu zagnieżdżonego.
Kliknij dwukrotnie osadzony wykres, aby wyświetlić jego miejsca docelowe.
Kliknij kartę Tekst, aby przełączyć się na widok XML. Do wykresu został dodany zagnieżdżony diagram nawigacji. Ten graf nawigacyjny ma własne elementy
navigation
, własny identyfikator i atrybutstartDestination
, który wskazuje na pierwszy element docelowy w grafu zagnieżdżonym:<?xml version="1.0" encoding="utf-8"?> <navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" app:startDestination="@id/mainFragment"> <fragment android:id="@+id/mainFragment" android:name="com.example.cashdog.cashdog.MainFragment" android:label="fragment_main" tools:layout="@layout/fragment_main" > <action android:id="@+id/action_mainFragment_to_sendMoneyGraph" app:destination="@id/sendMoneyGraph" /> <action android:id="@+id/action_mainFragment_to_viewBalanceFragment" app:destination="@id/viewBalanceFragment" /> </fragment> <fragment android:id="@+id/viewBalanceFragment" android:name="com.example.cashdog.cashdog.ViewBalanceFragment" android:label="fragment_view_balance" tools:layout="@layout/fragment_view_balance" /> <navigation android:id="@+id/sendMoneyGraph" app:startDestination="@id/chooseRecipient"> <fragment android:id="@+id/chooseRecipient" android:name="com.example.cashdog.cashdog.ChooseRecipient" android:label="fragment_choose_recipient" tools:layout="@layout/fragment_choose_recipient"> <action android:id="@+id/action_chooseRecipient_to_chooseAmountFragment" app:destination="@id/chooseAmountFragment" /> </fragment> <fragment android:id="@+id/chooseAmountFragment" android:name="com.example.cashdog.cashdog.ChooseAmountFragment" android:label="fragment_choose_amount" tools:layout="@layout/fragment_choose_amount" /> </navigation> </navigation>
W kodzie podaj identyfikator zasobu działania, które łączy graf główny z grafem zagnieżdżonym:
Kotlin
view.findNavController().navigate(R.id.action_mainFragment_to_sendMoneyGraph)
Java
Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_sendMoneyGraph);
- Na karcie Projekt możesz wrócić do grafu głównego, klikając Root (Root).
Odwoływanie się do innych grafów nawigacji za pomocą include
Innym sposobem modularyzacji struktury grafu jest uwzględnienie jednego grafu w innym za pomocą elementu <include>
w nadrzędnym grafie nawigacji. Dzięki temu można zdefiniować zawarty graf w osobnym module lub projekcie, co zmaksymalizuje możliwość ponownego użycia.
Ten fragment kodu pokazuje, jak używać funkcji <include>
:
<!-- (root) nav_graph.xml -->
<?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/fragment">
<include app:graph="@navigation/included_graph" />
<fragment
android:id="@+id/fragment"
android:name="com.example.myapplication.BlankFragment"
android:label="Fragment in Root Graph"
tools:layout="@layout/fragment_blank">
<action
android:id="@+id/action_fragment_to_second_graph"
app:destination="@id/second_graph" />
</fragment>
...
</navigation>
<!-- included_graph.xml -->
<?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/second_graph"
app:startDestination="@id/includedStart">
<fragment
android:id="@+id/includedStart"
android:name="com.example.myapplication.IncludedStart"
android:label="fragment_included_start"
tools:layout="@layout/fragment_included_start" />
</navigation>