חיבור רכיבים של ממשק המשתמש ל-NavController באמצעות NavigationUI

רכיב הניווט כולל את המחלקה NavigationUI. הכיתה הזו מכילה שיטות סטטיות שמנהלות את הניווט באמצעות סרגל האפליקציה העליון, חלונית ההזזה לניווט והניווט התחתון.

סרגל האפליקציה העליון

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

מסך שבו מוצג סרגל האפליקציות העליון
איור 1. מסך שבו מוצגת שורת אפליקציות בחלק העליון.

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

<navigation>
    <fragment ...
              android:label="Page title">
      ...
    </fragment>
</navigation>

כשמשתמשים ב-NavigationUI עם הטמעות של סרגל האפליקציות העליון שמפורטות בהמשך, אפשר לאכלס באופן אוטומטי את התווית שמצרפים ליעדים מהארגומנטים שסופקו ליעד באמצעות הפורמט {argName} בתווית.

NavigationUI תומך בסוגי שורת האפליקציה העליונה הבאים:

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

AppBarConfiguration

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

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

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

Kotlin

val appBarConfiguration = AppBarConfiguration(navController.graph)

Java

AppBarConfiguration appBarConfiguration =
        new AppBarConfiguration.Builder(navController.getGraph()).build();

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

Kotlin

val appBarConfiguration = AppBarConfiguration(setOf(R.id.main, R.id.profile))

Java

AppBarConfiguration appBarConfiguration =
        new AppBarConfiguration.Builder(R.id.main, R.id.profile).build();

יצירת סרגל כלים

כדי ליצור סרגל כלים באמצעות NavigationUI, קודם מגדירים את הסרגל בפעילות הראשית, כפי שמוצג:

<LinearLayout>
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar" />
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        ... />
    ...
</LinearLayout>

לאחר מכן, קוראים ל-setupWithNavController() מתוך method‏ onCreate() של הפעילות הראשית, כפי שמתואר בדוגמה הבאה:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    setContentView(R.layout.activity_main)

    ...

    val navController = findNavController(R.id.nav_host_fragment)
    val appBarConfiguration = AppBarConfiguration(navController.graph)
    findViewById<Toolbar>(R.id.toolbar)
        .setupWithNavController(navController, appBarConfiguration)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    ...

    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(navController.getGraph()).build();
    Toolbar toolbar = findViewById(R.id.toolbar);
    NavigationUI.setupWithNavController(
            toolbar, navController, appBarConfiguration);
}

כדי להגדיר את לחצן הניווט כך שיופיע כלחצן למעלה לכל היעדים, מעבירים קבוצה ריקה של מזהי יעדים ליעדים ברמה העליונה בזמן היצירה של AppBarConfiguration. אפשר להשתמש באפשרות הזו, למשל, אם יש לכם פעילות שנייה שאמור להופיע בה לחצן למעלה ב-Toolbar בכל היעדים. כך המשתמש יכול לחזור לפעילות ההורה אם אין יעדים אחרים בסטאק העורפי. אפשר להשתמש ב-setFallbackOnNavigateUpListener() כדי לקבוע את התנהגות ברירת המחדל במקרה ש-navigateUp() לא יבצע שום פעולה, כפי שמתואר בדוגמה הבאה:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    val appBarConfiguration = AppBarConfiguration(
        topLevelDestinationIds = setOf(),
        fallbackOnNavigateUpListener = ::onSupportNavigateUp
    )
    findViewById<Toolbar>(R.id.toolbar)
        .setupWithNavController(navController, appBarConfiguration)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...

    NavHostFragment navHostFragment = (NavHostFragment) supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder()
        .setFallbackOnNavigateUpListener(::onSupportNavigateUp)
        .build();
    Toolbar toolbar = findViewById(R.id.toolbar);
    NavigationUI.setupWithNavController(
            toolbar, navController, appBarConfiguration);
}

הכללת CollapsingToolbarLayout

כדי לכלול CollapsingToolbarLayout עם סרגל הכלים, קודם צריך להגדיר את סרגל הכלים ואת הפריסה שמסביב לפעילות, כפי שמתואר בהמשך:

<LinearLayout>
    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/tall_toolbar_height">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleGravity="top"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"/>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        ... />
    ...
</LinearLayout>

בשלב הבא, קוראים ל-setupWithNavController() מתוך method‏ onCreate של הפעילות הראשית, כפי שמוצג בהמשך:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    setContentView(R.layout.activity_main)

    ...

    val layout = findViewById<CollapsingToolbarLayout>(R.id.collapsing_toolbar_layout)
    val toolbar = findViewById<Toolbar>(R.id.toolbar)
    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    val appBarConfiguration = AppBarConfiguration(navController.graph)
    layout.setupWithNavController(toolbar, navController, appBarConfiguration)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    ...

    CollapsingToolbarLayout layout = findViewById(R.id.collapsing_toolbar_layout);
    Toolbar toolbar = findViewById(R.id.toolbar);
    NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(navController.getGraph()).build();
    NavigationUI.setupWithNavController(layout, toolbar, navController, appBarConfiguration);
}

סרגל הפעולות

כדי להוסיף תמיכה בניווט לסרגל הפעולות שמוגדר כברירת מחדל, צריך להפעיל את השיטה setupActionBarWithNavController() מהשיטה onCreate() של הפעילות הראשית, כפי שמתואר בהמשך. חשוב לזכור שצריך להצהיר על AppBarConfiguration מחוץ ל-onCreate(), כי משתמשים בו גם כשמשנים את ברירת המחדל של onSupportNavigateUp():

Kotlin

private lateinit var appBarConfiguration: AppBarConfiguration

...

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    appBarConfiguration = AppBarConfiguration(navController.graph)
    setupActionBarWithNavController(navController, appBarConfiguration)
}

Java

AppBarConfiguration appBarConfiguration;

...

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...

    NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
    NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
}

בשלב הבא, משנים את ברירת המחדל של onSupportNavigateUp() כדי לטפל בניווט למעלה:

Kotlin

override fun onSupportNavigateUp(): Boolean {
    val navController = findNavController(R.id.nav_host_fragment)
    return navController.navigateUp(appBarConfiguration)
            || super.onSupportNavigateUp()
}

Java

@Override
public boolean onSupportNavigateUp() {
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    return NavigationUI.navigateUp(navController, appBarConfiguration)
            || super.onSupportNavigateUp();
}

תמיכה באפשרויות שונות של שורת האפליקציות

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

לדוגמה, יכול להיות שבאחד מהיעדים שלכם נעשה שימוש ב-Toolbar רגיל, וביעד אחר נעשה שימוש ב-AppBarLayout כדי ליצור סרגל אפליקציות מורכב יותר עם כרטיסיות, כפי שמוצג באיור 2.

שתי וריאציות של סרגל האפליקציות העליון: סרגל כלים רגיל בצד ימין וסרגל כלים עם כרטיסיות בצד ימין
איור 2. שתי וריאציות של שורת האפליקציות. בצד ימין, Toolbar רגיל. בצד שמאל, סמל AppBarLayout עם Toolbar וכרטיסיות.

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

<LinearLayout>
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        ... />
    ...
</LinearLayout>

בשלב הבא מגדירים את קטע היעד שמשתמש בסרגל האפליקציות עם כרטיסיות:

<LinearLayout>
    <com.google.android.material.appbar.AppBarLayout
        ... />

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            ... />

        <com.google.android.material.tabs.TabLayout
            ... />

    </com.google.android.material.appbar.AppBarLayout>
    ...
</LinearLayout>

הלוגיקה של הגדרת הניווט זהה בשני הקטעים האלה, מלבד העובדה שצריך להפעיל את setupWithNavController() מתוך שיטת onViewCreated() של כל קטע, במקום לאתחל אותם מהפעילות:

Kotlin

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val navController = findNavController()
    val appBarConfiguration = AppBarConfiguration(navController.graph)

    view.findViewById<Toolbar>(R.id.toolbar)
            .setupWithNavController(navController, appBarConfiguration)
}

Java

@Override
public void onViewCreated(@NonNull View view,
                          @Nullable Bundle savedInstanceState) {
    NavController navController = Navigation.findNavController(view);
    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(navController.getGraph()).build();
    Toolbar toolbar = view.findViewById(R.id.toolbar);

    NavigationUI.setupWithNavController(
            toolbar, navController, appBarConfiguration);
}

קישור יעדים לפריטי תפריט

ב-NavigationUI יש גם כלים שיעזרו לכם לקשר יעדים לרכיבי ממשק משתמש שמבוססים על תפריטים. NavigationUI מכיל שיטה מסייעת, onNavDestinationSelected(), שמקבלת MenuItem יחד עם NavController שמארח את היעד המשויך. אם הערך של id ב-MenuItem תואם לערך של id ביעד, ה-NavController יוכל לנווט ליעד הזה.

לדוגמה, קטעי הקוד הבאים בפורמט XML מגדירים פריט תפריט ויעד עם id, ‏ details_page_fragment משותפים:

<?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"
    ... >

    ...

    <fragment android:id="@+id/details_page_fragment"
         android:label="@string/details"
         android:name="com.example.android.myapp.DetailsFragment" />
</navigation>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    ...

    <item
        android:id="@+id/details_page_fragment"
        android:icon="@drawable/ic_details"
        android:title="@string/details" />
</menu>

לדוגמה, אם התפריט נוסף דרך onCreateOptionsMenu() של הפעילות, תוכלו לשייך את פריטי התפריט ליעדים על ידי שינוי onOptionsItemSelected() של הפעילות כך שיפעיל את onNavDestinationSelected(), כפי שמתואר בדוגמה הבאה:

Kotlin

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    val navController = findNavController(R.id.nav_host_fragment)
    return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item)
}

Java

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    return NavigationUI.onNavDestinationSelected(item, navController)
            || super.onOptionsItemSelected(item);
}

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

הוספת חלונית ההזזה לניווט

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

חלונית פתוחה עם תפריט ניווט
איור 3. חלונית פתוחה שבה מוצג תפריט ניווט.

סמל המגירה מוצג בכל היעדים ברמה העליונה שמשתמשים ב-DrawerLayout.

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

לדוגמה, בפריסת הקוד הבאה נעשה שימוש ב-DrawerLayout עם שתי תצוגות צאצא: NavHostFragment שמכילה את התוכן הראשי ו-NavigationView שמכילה את התוכן של חלונית הניווט.

<?xml version="1.0" encoding="utf-8"?>
<!-- Use DrawerLayout as root container for activity -->
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- Layout to contain contents of main body of screen (drawer will slide over this) -->
    <androidx.fragment.app.FragmentContainerView
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:id="@+id/nav_host_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

    <!-- Container for contents of drawer - use NavigationView to make configuration easier -->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true" />

</androidx.drawerlayout.widget.DrawerLayout>

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

Kotlin

val appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)

Java

AppBarConfiguration appBarConfiguration =
        new AppBarConfiguration.Builder(navController.getGraph())
            .setDrawerLayout(drawerLayout)
            .build();

לאחר מכן, צריך לקרוא ל-setupWithNavController() בשיטה onCreate() של הפעילות הראשית, כפי שמתואר בהמשך:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    setContentView(R.layout.activity_main)

    ...

    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    findViewById<NavigationView>(R.id.nav_view)
        .setupWithNavController(navController)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    ...

    NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    NavigationView navView = findViewById(R.id.nav_view);
    NavigationUI.setupWithNavController(navView, navController);
}

החל מגרסה Navigation 2.4.0-alpha01, המצב של כל פריט בתפריט נשמר ומוחזר כשמשתמשים ב-setupWithNavController.

ניווט בחלק התחתון

NavigationUI יכול גם לטפל בניווט בתחתית המסך. כשמשתמש בוחר פריט בתפריט, האירוע NavController קורא ל-onNavDestinationSelected() ומעדכן באופן אוטומטי את הפריט שנבחר בסרגל הניווט התחתון.

סרגל הניווט התחתון
איור 4. סרגל ניווט תחתון.

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

<LinearLayout>
    ...
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        ... />
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav"
        app:menu="@menu/menu_bottom_nav" />
</LinearLayout>

לאחר מכן, צריך לקרוא ל-setupWithNavController() בשיטה onCreate() של הפעילות הראשית, כפי שמתואר בהמשך:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    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) {
    setContentView(R.layout.activity_main);

    ...

    NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    BottomNavigationView bottomNav = findViewById(R.id.bottom_nav);
    NavigationUI.setupWithNavController(bottomNav, navController);
}

החל מגרסה Navigation 2.4.0-alpha01, המצב של כל פריט בתפריט נשמר ומוחזר כשמשתמשים ב-setupWithNavController.

האזנה לאירועי ניווט

האינטראקציה עם NavController היא הדרך העיקרית לניווט בין יעדים. ה-NavController אחראי להחליף את התוכן של NavHost ביעד החדש. במקרים רבים, רכיבי ממשק המשתמש – כמו סרגל האפליקציות העליון או אמצעי ניווט מתמידים אחרים כמו BottomNavigationBar – נמצאים מחוץ ל-NavHost וצריך לעדכן אותם כשעוברים בין יעדים.

ל-NavController יש ממשק OnDestinationChangedListener שנקרא כשהיעד הנוכחי של NavController או הארגומנטים שלו משתנים. אפשר לרשום מאזין חדש באמצעות השיטה addOnDestinationChangedListener(). הערה: כשקוראים לפונקציה addOnDestinationChangedListener(), אם היעד הנוכחי קיים, הוא נשלח מיד למאזין.

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

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

Kotlin

navController.addOnDestinationChangedListener { _, destination, _ ->
   if(destination.id == R.id.full_screen_destination) {
       toolbar.visibility = View.GONE
       bottomNavigationView.visibility = View.GONE
   } else {
       toolbar.visibility = View.VISIBLE
       bottomNavigationView.visibility = View.VISIBLE
   }
}

Java

navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
   @Override
   public void onDestinationChanged(@NonNull NavController controller,
           @NonNull NavDestination destination, @Nullable Bundle arguments) {
       if(destination.getId() == R.id.full_screen_destination) {
           toolbar.setVisibility(View.GONE);
           bottomNavigationView.setVisibility(View.GONE);
       } else {
           toolbar.setVisibility(View.VISIBLE);
           bottomNavigationView.setVisibility(View.VISIBLE);
       }
   }
});

פונקציות האזנה מבוססות-ארגומנט

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

<?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"
    android:id="@+id/navigation\_graph"
    app:startDestination="@id/fragmentOne">
    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.android.navigation.FragmentOne"
        android:label="FragmentOne">
        <action
            android:id="@+id/action\_fragmentOne\_to\_fragmentTwo"
            app:destination="@id/fragmentTwo" />
    </fragment>
    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.android.navigation.FragmentTwo"
        android:label="FragmentTwo">
        <argument
            android:name="ShowAppBar"
            android:defaultValue="true" />
    </fragment>
</navigation>

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

עכשיו אפשר להוסיף OnDestinationChangedListener ב-Activity:

Kotlin

navController.addOnDestinationChangedListener { _, _, arguments ->
    appBar.isVisible = arguments?.getBoolean("ShowAppBar", false) == true
}

Java

navController.addOnDestinationChangedListener(
        new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(
                    @NonNull NavController controller,
                    @NonNull NavDestination destination,
                    @Nullable Bundle arguments
            ) {
                boolean showAppBar = false;
                if (arguments != null) {
                    showAppBar = arguments.getBoolean("ShowAppBar", false);
                }
                if(showAppBar) {
                    appBar.setVisibility(View.VISIBLE);
                } else {
                    appBar.setVisibility(View.GONE);
                }
            }
        }
);

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

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

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

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

דוגמיות

Codelabs

פוסטים בבלוג

סרטונים