עיצוב תרשים הניווט

רכיב הניווט משתמש בתרשים ניווט כדי לנהל את הניווט באפליקציה. תרשים הניווט הוא מבנה נתונים שמכיל כל יעד באפליקציה ואת החיבורים ביניהם.

סוגי היעדים

יש שלושה סוגים כלליים של יעדים: אירוח, תיבת דו-שיח ופעילות. בטבלה הבאה מפורטים שלושת סוגי היעד האלה והמטרות שלהם.

סוג

תיאור

תרחישים לדוגמה

מתארח

ממלא את כל מארח הניווט. כלומר, הגודל של יעד מתארח זהה לגודל של מארח הניווט, ויעדים קודמים לא גלויים.

המסך הראשי והמסך המפורט.

תיבת דו-שיח

הצגת רכיבי ממשק משתמש של שכבת-על. ממשק המשתמש הזה לא קשור למיקום של מארח הניווט או לגודל שלו. היעדים הקודמים מוצגים מתחת ליעד.

התראות, בחירות, טפסים.

פעילות

מייצג מסכים או תכונות ייחודיים באפליקציה.

נקודת יציאה לתרשים הניווט שמפעילה פעילות חדשה ב-Android שמנוהלת בנפרד מרכיב הניווט.

בפיתוח מודרני של Android, אפליקציה מורכבת מפעילות אחת. לכן, מומלץ להשתמש ביעדים של פעילויות כשמתבצעת אינטראקציה עם פעילויות של צד שלישי או כחלק מתהליך ההעברה.

המסמך הזה מכיל דוגמאות ליעדים מתארחים, שהם היעדים הנפוצים והבסיסיים ביותר. במדריכים הבאים מפורט מידע על יעדי המודעות האחרים:

מסגרות

תהליך העבודה הכללי זהה בכל מקרה, אבל האופן שבו יוצרים מארח ותרשימים של ניווט תלוי בסביבת ה-UI שבה משתמשים.

  • כתיבה: משתמשים ב-composable‏ NavHost. מוסיפים לו NavGraph באמצעות Kotlin DSL. יש שתי דרכים ליצור את התרשים:
    • כחלק מ-NavHost: יוצרים את תרשים הניווט ישירות כחלק מהוספת NavHost.
    • באופן פרוגרמטי: משתמשים ב-method‏ NavController.createGraph() כדי ליצור NavGraph ולהעביר אותו ישירות ל-NavHost.
  • קטעים: כשמשתמשים בקטעים עם מסגרת ממשק המשתמש של התצוגות, צריך להשתמש ב-NavHostFragment בתור המארח. יש כמה דרכים ליצור תרשים ניווט:
    • באופן פרוגרמטי: משתמשים ב-DSL של Kotlin כדי ליצור NavGraph ולהחיל אותו ישירות על NavHostFragment.
      • הפונקציה createGraph() שמשמשת עם Kotlin DSL גם לקטעי קוד וגם ל-Compose היא זהה.
    • XML: כותבים את מארח הניווט והתרשים ישירות ב-XML.
    • עורך Android Studio: אפשר להשתמש בעורך GUI ב-Android Studio כדי ליצור ולשנות את התרשים כקובץ משאב XML.

פיתוח נייטיב

ב-Compose, משתמשים באובייקט או במחלקה שניתן לסדרה כדי להגדיר מסלול. מסלול מתאר איך להגיע ליעד, ומכיל את כל המידע שנחוץ ליעד.

אפשר להשתמש בהערה @Serializable כדי ליצור באופן אוטומטי את השיטות הנדרשות לסריאליזציה ולדה-סריאליזציה של סוגי המסלולים. ההערה הזו מסופקת על ידי הפלאגין של Kotlin Serialization. כך מוסיפים את הפלאגין הזה.

אחרי שמגדירים את המסלולים, משתמשים ב-composable‏ NavHost כדי ליצור את תרשים הניווט. דוגמה:

@Serializable
object Profile
@Serializable
object FriendsList

val navController = rememberNavController()

NavHost(navController = navController, startDestination = Profile) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
    // Add more destinations similarly.
}
  1. אובייקט שניתן לסריאליזציה מייצג כל אחד משני המסלולים, Profile ו-FriendsList.
  2. הקריאה ל-composable של NavHost מעבירה NavController ומסלול ליעד ההתחלה.
  3. פונקציית הלוגריתם הבינארי (lambda) שהועברה ל-NavHost בסופו של דבר קוראת ל-NavController.createGraph() ומחזירה NavGraph.
  4. כל מסלול מסופק כארגומנט מסוג ל-NavGraphBuilder.composable<T>(), שמוסיף את היעד ל-NavGraph שנוצר.
  5. פונקציית ה-lambda שהועברה אל composable היא זו שמוצגת ב-NavHost ליעד הזה.

הסבר על הפונקציה lambda

כדי להבין טוב יותר את הפונקציה lambda שיוצרת את NavGraph, נזכיר שאפשר ליצור את NavGraph בנפרד באמצעות NavController.createGraph() ולהעביר אותו ישירות ל-NavHost כדי ליצור את אותו תרשים כמו בקטע הקודם:

val navGraph by remember(navController) {
  navController.createGraph(startDestination = Profile)) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
  }
}
NavHost(navController, navGraph)

העברת ארגומנטים

אם אתם צריכים להעביר נתונים ליעד, צריך להגדיר את המסלול באמצעות כיתה עם פרמטרים. לדוגמה, המסלול Profile הוא סוג נתונים עם פרמטר name.

@Serializable
data class Profile(val name: String)

בכל פעם שצריך להעביר ארגומנטים ליעד הזה, יוצרים מופע של כיתה המסלול ומעבירים את הארגומנטים למבנה הכיתה.

עבור ארגומנטים אופציונליים, יוצרים שדות nullable עם ערך ברירת מחדל.

@Serializable
data class Profile(val nickname: String? = null)

אחזור מכונה של מסלול

אפשר לקבל את מופע המסלול באמצעות NavBackStackEntry.toRoute() או SavedStateHandle.toRoute(). כשיוצרים יעד באמצעות composable(), הערך NavBackStackEntry זמין כפרמטר.

@Serializable
data class Profile(val name: String)

val navController = rememberNavController()

NavHost(navController = navController, startDestination = Profile(name="John Smith")) {
    composable<Profile> { backStackEntry ->
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(name = profile.name) }
}

שימו לב לדברים הבאים בקטע הקוד הזה:

  • המסלול Profile מציין את יעד ההתחלה בתרשים הניווט, כאשר "John Smith" הוא הארגומנט של name.
  • היעד עצמו הוא הבלוק composable<Profile>{}.
  • ה-composable של ProfileScreen מקבל את הערך של profile.name כארגומנטים שלו name.
  • לכן, הערך "John Smith" מועבר אל ProfileScreen.

דוגמה מינימלית

דוגמה מלאה לשימוש בשילוב של NavController ו-NavHost:

@Serializable
data class Profile(val name: String)

@Serializable
object FriendsList

// Define the ProfileScreen composable.
@Composable
fun ProfileScreen(
    profile: Profile
    onNavigateToFriendsList: () -> Unit,
  ) {
  Text("Profile for ${profile.name}")
  Button(onClick = { onNavigateToFriendsList() }) {
    Text("Go to Friends List")
  }
}

// Define the FriendsListScreen composable.
@Composable
fun FriendsListScreen(onNavigateToProfile: () -> Unit) {
  Text("Friends List")
  Button(onClick = { onNavigateToProfile() }) {
    Text("Go to Profile")
  }
}

// Define the MyApp composable, including the `NavController` and `NavHost`.
@Composable
fun MyApp() {
  val navController = rememberNavController()
  NavHost(navController, startDestination = Profile(name = "John Smith")) {
    composable<Profile> { backStackEntry ->
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(
            profile = profile,
            onNavigateToFriendsList = {
                navController.navigate(route = FriendsList)
            }
        )
    }
    composable<FriendsList> {
      FriendsListScreen(
        onNavigateToProfile = {
          navController.navigate(
            route = Profile(name = "Aisha Devi")
          )
        }
      )
    }
  }
}

כפי שמוצג בקטע הקוד, במקום להעביר את NavController לרכיבים הניתנים לקישור, חושפים אירוע ל-NavHost. כלומר, לרכיבי ה-Composable צריך להיות פרמטר מסוג () -> Unit, ש-NavHost מעביר לו פונקציית lambda שמפעילה את NavController.navigate().

קטעים

כפי שמתואר בקטעים הקודמים, כשמשתמשים בקטעים יש לכם אפשרות ליצור תרשים ניווט באופן פרוגרמטי באמצעות Kotlin DSL,‏ XML או העורך של Android Studio.

בקטעים הבאים מפורטות הגישות השונות.

באופן פרוגרמטי

‏DSL של Kotlin מספק דרך פרוגרמטית ליצירת תרשים ניווט עם קטעים. מבחינות רבות, הפתרון הזה מסודר ומודרני יותר מאשר שימוש בקובץ משאבים מסוג XML.

בדוגמה הבאה מתואר יישום של תרשים ניווט בשני מסכים.

קודם צריך ליצור את NavHostFragment, שאסור לכלול אלמנט app:navGraph:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

בשלב הבא, מעבירים את id של NavHostFragment אל NavController.findNavController. כך משייכים את NavController ל-NavHostFragment.

כתוצאה מכך, הקריאה ל-NavController.createGraph() מקשרת את התרשים ל-NavController, וכתוצאה מכך גם ל-NavHostFragment:

@Serializable
data class Profile(val name: String)

@Serializable
object FriendsList

// Retrieve the NavController.
val navController = findNavController(R.id.nav_host_fragment)

// Add the graph to the NavController with `createGraph()`.
navController.graph = navController.createGraph(
    startDestination = Profile(name = "John Smith")
) {
    // Associate each destination with one of the route constants.
    fragment<ProfileFragment, Profile> {
        label = "Profile"
    }

    fragment<FriendsListFragment, FriendsList>() {
        label = "Friends List"
    }

    // Add other fragment destinations similarly.
}

השימוש ב-DSL באופן הזה דומה מאוד לתהליך העבודה שמתואר בקטע הקודם בנושא Compose. לדוגמה, גם שם וגם כאן, הפונקציה NavController.createGraph() יוצרת את NavGraph. באופן דומה, בעוד ש-NavGraphBuilder.composable() מוסיף לתרשים יעדים שאפשר ליצור מהם קומפוזיציות, כאן NavGraphBuilder.fragment() מוסיף יעד של קטע קוד.

מידע נוסף על השימוש ב-DSL של Kotlin זמין במאמר יצירת תרשים באמצעות ה-DSL של NavGraphBuilder.

XML

אתם יכולים לכתוב את קובץ ה-XML בעצמכם. הדוגמה הבאה זהה לדוגמה עם שני המסכים בקטע הקודם.

קודם כול יוצרים NavHostFragment. הוא משמש כמארח הניווט שמכיל את תרשים הניווט בפועל.

הטמעה מינימלית של NavHostFragment:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:navGraph="@navigation/nav_graph" />

</FrameLayout>

השדה NavHostFragment מכיל את המאפיין app:navGraph. משתמשים במאפיין הזה כדי לחבר את תרשים הניווט למארח הניווט. בדוגמה הבאה מוסבר איך אפשר להטמיע את התרשים:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/profile">

    <fragment
        android:id="@+id/profile"
        android:name="com.example.ProfileFragment"
        android:label="Profile">

        <!-- Action to navigate from Profile to Friends List. -->
        <action
            android:id="@+id/action_profile_to_friendslist"
            app:destination="@id/friendslist" />
    </fragment>

    <fragment
        android:id="@+id/friendslist"
        android:name="com.example.FriendsListFragment"
        android:label="Friends List" />

    <!-- Add other fragment destinations similarly. -->
</navigation>

פעולות משמשות להגדרת החיבורים בין יעדים שונים. בדוגמה הזו, קטע הקוד profile מכיל פעולה שמנווטת אל friendslist. מידע נוסף זמין במאמר שימוש בפעולות ובקטעים של ניווט.

עריכה

אפשר לנהל את תרשים הניווט של האפליקציה באמצעות כלי העריכה של הניווט ב-Android Studio. זהו למעשה ממשק משתמש גרפי שאפשר להשתמש בו כדי ליצור ולערוך את קובץ ה-NavigationFragment XML, כפי שמוצג בסעיף הקודם.

מידע נוסף זמין במאמר כלי הניווט.

תרשימים בתצוגת עץ

אפשר גם להשתמש בתרשים בתצוגת עץ. המשמעות היא שימוש בגרף כיעד ניווט. מידע נוסף זמין במאמר תצוגת עץ של גרפים.

מקורות מידע נוספים

למידע נוסף על מושגי ניווט בסיסיים, אפשר לעיין במדריכים הבאים: