בדרך כלל, הכי טוב לייצג תהליכי התחברות, אשפים או תהליכי משנה אחרים באפליקציה באמצעות תרשימי ניווט מקוננים. כשמקננים תהליכי ניווט משניים עצמאיים בצורה הזו, קל יותר להבין ולנהל את התהליך הראשי של ממשק המשתמש של האפליקציה.
בנוסף, אפשר לעשות שימוש חוזר בתרשימים מוטמעים. הם גם מספקים רמה של הכמסה – ליעדים מחוץ לתרשים המקונן אין גישה ישירה לאף אחד מהיעדים בתוך התרשים המקונן. במקום זאת, הם צריכים navigate()
לתרשים המקונן עצמו, שבו הלוגיקה הפנימית יכולה להשתנות בלי להשפיע על שאר התרשים.
דוגמה
גרף הניווט ברמה העליונה של האפליקציה צריך להתחיל ביעד הראשוני שהמשתמש רואה כשהוא מפעיל את האפליקציה, ולכלול את היעדים שהוא רואה כשהוא עובר בין חלקי האפליקציה.

לדוגמה, אם רוצים שהמשתמש יראה את המסכים title_screen ו-register רק כשהאפליקציה מופעלת בפעם הראשונה, אפשר להשתמש בתרשים הניווט ברמה העליונה שמוצג באיור 1. לאחר מכן, פרטי המשתמש נשמרים, ובפעם הבאה שהמשתמש יפתח את האפליקציה, הוא יועבר ישירות למסך ההתאמה.
מומלץ להגדיר את מסך ההתאמה כיעד ההתחלה של תרשים הניווט ברמה העליונה, ולהעביר את מסכי הכותרת וההרשמה לתרשים מקונן, כמו שמוצג באיור 1:

כשמסך ההתאמה מופעל, בודקים אם יש משתמש רשום. אם המשתמש לא רשום, מעבירים אותו למסך ההרשמה.
למידע נוסף על תרחישים של ניווט מותנה, ראו ניווט מותנה.
כתיבה
כדי ליצור גרף ניווט מקונן באמצעות Compose, משתמשים בפונקציה NavGraphBuilder.navigation()
. משתמשים ב-navigation()
בדיוק כמו בפונקציות NavGraphBuilder.composable()
ו-NavGraphBuilder.dialog()
כשמוסיפים יעדים לגרף.
ההבדל העיקרי הוא שהפקודה navigation
יוצרת תרשים מקונן ולא יעד חדש. לאחר מכן קוראים לפונקציות composable()
ו-dialog()
בתוך פונקציית הלמדה של navigation()
כדי להוסיף יעדים לגרף המקונן.
כדאי לשים לב איך קטע הקוד הבא מטמיע את התרשים באיור 2 באמצעות 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 }
}
}
)
}
}
}
כדי לנווט ישירות ליעד מוטמע, משתמשים בסוג מסלול כמו בכל יעד אחר. הסיבה לכך היא שמסלולים הם מושג גלובלי שמשמש לזיהוי יעדים שאפשר לנווט אליהם מכל מסך:
navController.navigate(route = Match)
XML
כשמשתמשים ב-XML, אפשר להשתמש בכלי לעריכת ניווט כדי ליצור את הגרף המקונן. כדי לעשות זאת:
- בכלי לעריכת ניווט, לוחצים לחיצה ארוכה על המקש Shift ולוחצים על יעדי הניווט שרוצים לכלול בתרשים המקונן.
לוחצים לחיצה ימנית כדי לפתוח את תפריט ההקשר, ובוחרים באפשרות העברה לתרשים מקונן > תרשים חדש. היעדים מופיעים בתרשים מקונן. איור 2 מציג תרשים מקונן בכלי לעריכת הניווט:
איור 2. תרשים מקונן בכלי לעריכת ניווט לוחצים על הגרף המקונן. המאפיינים הבאים מופיעים בחלונית מאפיינים:
- Type (סוג), שמכיל את הערך Nested Graph (גרף מקונן)
- ID, שמכיל מזהה שהמערכת מקצה לגרף המקונן. המזהה הזה משמש להתייחסות לתרשים המקונן מהקוד שלכם.
לוחצים לחיצה כפולה על הגרף המקונן כדי להציג את היעדים שלו.
לוחצים על הכרטיסייה Text כדי לעבור לתצוגת ה-XML. נוסף לגרף גרף ניווט מקונן. לתרשים הניווט הזה יש רכיבים משלו
navigation
יחד עם מזהה משלו ומאפייןstartDestination
שמפנה ליעד הראשון בתרשים המקונן:<?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>
בקוד, מעבירים את מזהה המשאב של הפעולה שמקשרת בין הגרף הראשי לגרף המקונן:
Kotlin
view.findNavController().navigate(R.id.action_mainFragment_to_sendMoneyGraph)
Java
Navigation.findNavController(view).navigate(R.id.action_mainFragment_to_sendMoneyGraph);
- בכרטיסייה עיצוב, לוחצים על Root כדי לחזור לגרף הבסיסי.
הפניה לגרפים אחרים של ניווט באמצעות include
דרך נוספת להפוך את מבנה הגרף למודולרי היא לכלול גרף אחד בתוךגרף אחר באמצעות רכיב <include>
בגרף הניווט הראשי. כך אפשר להגדיר את הגרף הכלול במודול או בפרויקט נפרדים לגמרי, מה שמגדיל את האפשרות לשימוש חוזר.
בדוגמה הבאה אפשר לראות איך משתמשים בתג <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>