اتصال مؤلفه‌های میانای کاربر به NavController بااستفاده از NavigationUI

مؤلفه «ناوبری» شامل کلاس NavigationUI است. این کلاس حاوی روش‌های ثابتی است که پیمایش با نوار برنامه بالا، کشوی پیمایش، و پیمایش پایین را مدیریت می‌کند.

نوار برنامه بالا

نوار برنامه بالا مکان ثابتی را در بالای برنامه برای نمایش اطلاعات و کنش‌های صفحه فعلی فراهم می‌کند.

صفحه‌نمایشی که نوار برنامه برتر را نشان می‌دهد
شکل ۱. صفحه‌نمایشی که نوار برنامه برتر را نشان می‌دهد.

‫NavigationUI حاوی روش‌هایی است که وقتی کاربران در برنامه‌تان پیمایش می‌کنند، محتوا را به‌طور خودکار در نوار برنامه بالایی به‌روز می‌کند. برای مثال، NavigationUI از برچسب‌های مقصد از نمودار پیمایش شما استفاده می‌کند تا عنوان نوار برنامه بالایی را به‌روز نگه دارد.

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

هنگام استفاده از NavigationUI با پیاده‌سازی‌های نوار برنامه بالا که در زیر بحث شده است، برچسبی که به مقصدها پیوست می‌کنید می‌تواند به‌طور خودکار از آرگومان‌های ارائه‌شده به مقصد بااستفاده از قالب {argName} در برچسب شما پر شود.

NavigationUI از انواع نوار برنامه برتر زیر پشتیبانی می‌کند:

برای اطلاعات بیشتر درباره نوارهای برنامه، به راه‌اندازی نوار برنامه مراجعه کنید.

AppBarConfiguration

NavigationUI از شیء AppBarConfiguration برای مدیریت رفتار دکمه «پیمایش» در گوشه بالا سمت راست ناحیه نمایش برنامه شما استفاده می‌کند. رفتار دکمه «پیمایش» بسته به اینکه کاربر در مقصد سطح بالا باشد یا نه تغییر می‌کند.

مقصد سطح بالا ریشه یا بالاترین سطح مقصد در مجموعه‌ای از مقصدهای مرتبط با سلسله‌مراتب است. مقصدهای سطح بالا دکمه «بالا» را در نوار برنامه بالا نمایش نمی‌دهند زیرا مقصد سطح بالاتری وجود ندارد. به‌طور پیش‌فرض، مقصد شروع برنامه‌تان تنها مقصد سطح بالا است.

وقتی کاربر در مقصد سطح بالا قرار دارد، دکمه «پیمایش» به نماد کشو تبدیل می‌شود اگر مقصد از DrawerLayout استفاده کند. اگر مقصد از DrawerLayout استفاده نکند، دکمه «پیمایش» پنهان می‌شود. وقتی کاربر در مقصد دیگری باشد، دکمه «پیمایش» به‌صورت دکمه «بالا» نشان داده می‌شود. برای پیکربندی دکمه «پیمایش» بااستفاده از مقصد شروع به‌عنوان مقصد سطح بالا، یک شیء AppBarConfiguration ایجاد کنید و آن را در نمودار پیمایش مربوطه ارسال کنید، همان‌طور که در زیر نشان داده شده است:

کاتلین

val appBarConfiguration = AppBarConfiguration(navController.graph)

جاوا

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

در برخی موارد، ممکن است لازم باشد به‌جای استفاده از مقصد شروع پیش‌فرض، چندین مقصد سطح بالا تعریف کنید. استفاده از BottomNavigationView یک مورد استفاده رایج برای این کار است، جایی که ممکن است صفحه‌های هم‌سطحی داشته باشید که ازنظر سلسله‌مراتبی با یکدیگر مرتبط نیستند و هرکدام ممکن است مجموعه مقصدهای مرتبط خود را داشته باشند. برای مواردی مانند این، می‌توانید مجموعه‌ای از شناسه‌های مقصد را به سازنده ارسال کنید، همان‌طور که در زیر نشان داده شده است:

کاتلین

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

جاوا

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() را از روش onCreate() فعالیت اصلی‌تان فراخوانی کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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)
}

جاوا

@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() هیچ کاری انجام نمی‌دهد، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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)
}

جاوا

@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() را از روش onCreate فعالیت اصلی‌تان فراخوانی کنید، همان‌طور که در زیر نشان داده شده است:

کاتلین

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)
}

جاوا

@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() نیز از آن استفاده می‌کنید:

کاتلین

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)
}

جاوا

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() را لغو کنید تا پیمایش «بالا» را مدیریت کنید:

کاتلین

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

جاوا

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

پشتیبانی از گونه‌های نوار برنامه

افزودن نوار برنامه بالا به فعالیتتان زمانی خوب کار می‌کند که چیدمان نوار برنامه برای هر مقصد در برنامه‌تان مشابه باشد. اما اگر نوار برنامه بالا در مقصدهای مختلف به‌طور قابل‌توجهی تغییر می‌کند، بهتر است نوار برنامه بالا را از فعالیتتان بردارید و به‌جای آن، آن را در هر قطعه مقصد تعریف کنید.

به‌عنوان مثال، یکی از مقصدهای شما ممکن است از Toolbar استاندارد استفاده کند، درحالی‌که مقصد دیگر از AppBarLayout برای ایجاد نوار برنامه پیچیده‌تر با برگه‌ها استفاده می‌کند، همان‌طور که در شکل ۲ نشان داده شده است.

دو نوع نوار برنامه بالا؛ نوار ابزار استاندارد در سمت چپ، و
            طرح‌بندی نوار برنامه با نوار ابزار و برگه‌ها در سمت راست
شکل ۲. دو نوع نوار برنامه. در سمت راست، یک استاندارد 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() هر قطعه فراخوانی کنید، به‌جای اینکه آن‌ها را از فعالیت مقداردهی اولیه کنید:

کاتلین

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

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

جاوا

@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()، گزینه‌های منو را با مقصدها مرتبط کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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

جاوا

@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 پیمایش می‌کند.

افزودن کشوی پیمایش

کشوی پیمایش پانل میانای کاربری است که منو پیمایش اصلی برنامه را نشان می‌دهد. وقتی کاربر نماد کشو را در نوار برنامه لمس می‌کند یا وقتی کاربر انگشتش را از لبه چپ صفحه تند می‌کشد، کشو ظاهر می‌شود.

کشوی باز که منو پیمایش را نشان می‌دهد
شکل ۳.‏ کشوی بازشده‌ای که منو پیمایش را نمایش می‌دهد.

نماد کشو در همه مقصدهای سطح بالا که از 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 به نمودار پیمایش خود متصل کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

val appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)

جاوا

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

سپس، در کلاس فعالیت اصلی‌تان، setupWithNavController() را از روش onCreate() فعالیت اصلی‌تان فراخوانی کنید، همان‌طور که در زیر نشان داده شده است:

کاتلین

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)
}

جاوا

@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() را فرامی‌خواند و گزینه انتخاب‌شده را به‌طور خودکار در نوار پیمایش پایین به‌روز می‌کند.

نوار پیمایش پایین
شکل ۴. نوار پیمایش پایین.

برای ایجاد نوار پیمایش پایین در برنامه‌تان، ابتدا نوار را در فعالیت اصلی‌تان تعریف کنید، همان‌طور که در زیر نشان داده شده است:

<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() فعالیت اصلی‌تان فراخوانی کنید، همان‌طور که در زیر نشان داده شده است:

کاتلین

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)
}

جاوا

@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 خودتان، می‌توانید این عناصر میانای کاربر را به‌طور انتخابی براساس مقصد هدف نشان دهید یا پنهان کنید، همان‌طور که در مثال زیر نشان داده شده است:

کاتلین

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
   }
}

جاوا

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 اضافه کنیم:

کاتلین

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

جاوا

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

پست‌های وبلاگ

ویدیوها