Ścieżki logowania, kreatory i inne podścieżki w aplikacji najlepiej przedstawić jako zagnieżdżone wykresy nawigacji. Dzięki zagnieżdżaniu w ten sposób samodzielnych podścieżek nawigacji główna ścieżka interfejsu aplikacji jest łatwiejsza do zrozumienia i zarządzania.
Dodatkowo zagnieżdżone wykresy można ponownie wykorzystać. Zapewniają też pewien poziom hermetyzacji – miejsca docelowe poza zagnieżdżonym wykresem nie mają bezpośredniego dostępu do żadnego z miejsc docelowych w zagnieżdżonym wykresie. Zamiast tego powinny one
navigate() do samego zagnieżdżonego wykresu, w którym logika wewnętrzna może
zmieniać się bez wpływu na resztę wykresu.
Przykład
Wykres nawigacji najwyższego poziomu w aplikacji powinien zaczynać się od początkowego miejsca docelowego, które użytkownik widzi po uruchomieniu aplikacji, i zawierać miejsca docelowe, które widzi podczas korzystania z aplikacji.
Na przykładzie wykresu nawigacji najwyższego poziomu z rysunku 1 załóżmy, że chcesz wymagać, aby użytkownik widział ekrany title_screen i register tylko przy pierwszym uruchomieniu aplikacji. Następnie informacje o użytkowniku są przechowywane, a przy kolejnych uruchomieniach aplikacji użytkownik powinien być przenoszony bezpośrednio na ekran match.
Zalecamy ustawienie ekranu match jako początkowego miejsca docelowego wykresu nawigacji najwyższego poziomu i przeniesienie ekranów tytułu i rejestracji na zagnieżdżony wykres, jak pokazano na rysunku 1:
Po uruchomieniu ekranu dopasowania sprawdź, czy jest zarejestrowany użytkownik. Jeśli użytkownik nie jest zarejestrowany, przenieś go na ekran rejestracji.
Więcej informacji o scenariuszach nawigacji warunkowej znajdziesz w artykule Conditional navigation.
Utwórz
Aby utworzyć zagnieżdżony wykres nawigacji za pomocą Compose, użyj funkcji
NavGraphBuilder.navigation(). Podczas dodawania miejsc docelowych do wykresu używasz navigation() tak samo jak
NavGraphBuilder.composable() i NavGraphBuilder.dialog()
funkcji.
Główna różnica polega na tym, że funkcja navigation tworzy zagnieżdżony wykres, a nie nowe miejsce docelowe. Następnie w lambdzie funkcji navigation() wywołujesz funkcje composable() i dialog(), aby dodać miejsca docelowe do zagnieżdżonego wykresu.
Zobacz, jak poniższy fragment kodu implementuje wykres na rysunku 2 za pomocą 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 każdego innego miejsca docelowego. Wynika to z tego, że trasy są koncepcją globalną służącą do identyfikowania miejsc docelowych, do których można przejść z dowolnego ekranu:
navController.navigate(route = Match)
XML
Jeśli używasz XML, możesz utworzyć zagnieżdżony wykres za pomocą Edytora nawigacji. Aby to zrobić:
- W Edytorze nawigacji naciśnij i 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ą umieszczone w zagnieżdżonym wykresie. Rysunek 2 przedstawia zagnieżdżony wykres w Edytorze nawigacji:
Rysunek 2. Zagnieżdżony wykres w Edytorze nawigacji Kliknij zagnieżdżony wykres. W panelu Atrybuty pojawią się te atrybuty:
- Typ, który zawiera "Zagnieżdżony wykres"
- Identyfikator, który zawiera przypisany przez system identyfikator zagnieżdżonego wykresu. Ten identyfikator służy do odwoływania się do zagnieżdżonego wykresu w kodzie.
Kliknij dwukrotnie zagnieżdżony wykres, aby wyświetlić jego miejsca docelowe.
Kliknij kartę Tekst , aby przełączyć się na widok XML. Do wykresu został dodany zagnieżdżony wykres nawigacji. Ten wykres nawigacji ma własne elementy
navigation, własny identyfikator i atrybutstartDestination, który wskazuje pierwsze miejsce docelowe w zagnieżdżonym wykresie:<?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 przekaż identyfikator zasobu działania łączącego wykres główny z zagnieżdżonym wykresem:
Kotlin
view.findNavController().navigate(R.id.action_mainFragment_to_sendMoneyGraph)
Java
Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_sendMoneyGraph);
- Wróć do karty Projekt i kliknij Główny, aby wrócić do wykresu głównego.
Odniesienia do innych wykresów nawigacji za pomocą include
Innym sposobem na modularyzację struktury wykresu jest dołączenie jednego wykresu do
drugiego za pomocą elementu <include> w nadrzędnym wykresie nawigacji. Dzięki temu dołączony wykres można zdefiniować w osobnym module lub projekcie, co maksymalizuje możliwość ponownego wykorzystania.
Poniższy fragment kodu pokazuje, jak używać elementu <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>