ربط مكونات واجهة المستخدم بـ NavController باستخدام واجهة مستخدم التنقل

يتضمن مكوِّن التنقل فئة NavigationUI. تحتوي هذه الفئة على طرق ثابتة تدير التنقل من خلال شريط التطبيق العلوي ودرج التنقل والتنقل السفلي.

شريط التطبيق العلوي

يوفّر شريط التطبيق العلوي مكانًا ثابتًا على طول الجزء العلوي من تطبيقك لعرض المعلومات والإجراءات من الشاشة الحالية.

شاشة تعرض شريط تطبيق علوي
الشكل 1. شاشة تعرض شريط التطبيق العلوي.

يحتوي NavigationUI على طرق تعمل تلقائيًا على تحديث المحتوى في شريط التطبيق العلوي أثناء تنقّل المستخدمين في التطبيق. على سبيل المثال، يستخدم NavigationUI تصنيفات الوجهات من الرسم البياني للتنقل للحفاظ على تحديث عنوان شريط التطبيق العلوي.

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

عند استخدام NavigationUI مع عمليات تنفيذ شريط التطبيقات العلوي التي تمت مناقشتها أدناه، يمكن تلقائيًا ملء التصنيف الذي ترفقه بالوجهات من الوسيطات المُقدَّمة إلى الوجهة باستخدام تنسيق {argName} في تصنيفك.

يتوافق NavigationUI مع أفضل أنواع أشرطة التطبيقات التالية:

لمزيد من المعلومات عن أشرطة التطبيقات، يُرجى الاطّلاع على إعداد شريط التطبيقات.

إعدادات AppBar

يستخدم NavigationUI الكائن AppBarConfiguration لإدارة سلوك زر "التنقل" في أعلى يمين منطقة عرض التطبيق. يتغير سلوك زر التنقل بناءً على ما إذا كان المستخدم في وجهة المستوى الأعلى أم لا.

الوجهة ذات المستوى الأعلى هي الجذر أو الوجهة ذات المستوى الأعلى في مجموعة من الوجهات المرتبطة بالتسلسل الهرمي. لا تعرض الوجهات ذات المستوى الأعلى زر لأعلى في شريط التطبيق العلوي لأنه لا توجد وجهة ذات مستوى أعلى. بشكل تلقائي، تكون وجهة بدء تطبيقك هي الوجهة الوحيدة ذات المستوى الأعلى.

عندما يكون المستخدم في وجهة ذات مستوى أعلى، يصبح زر التنقّل رمز الدرج إذا كانت الوجهة تستخدم DrawerLayout. إذا كانت الوجهة لا تستخدم DrawerLayout، سيكون زر التنقّل مخفيًا. عندما يكون المستخدِم في أي وجهة أخرى، يظهر زر "التنقل" كزرّ للأعلى . لإعداد زر "التنقل" باستخدام وجهة البدء فقط كوجهة ذات مستوى أعلى، أنشئ كائن AppBarConfiguration، ثم مرر في الرسم البياني للتنقل المقابل، كما هو موضّح أدناه:

Kotlin

val appBarConfiguration = AppBarConfiguration(navController.graph)

Java

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

في بعض الحالات، قد تحتاج إلى تحديد وجهات ذات مستوى أعلى متعددة بدلاً من استخدام وجهة البدء التلقائية. إنّ استخدام BottomNavigationView هو حالة استخدام شائعة لهذا الغرض، إذ قد يكون لديك شاشات شقيقة غير مرتبطة ببعضها البعض في تسلسل هرمي وقد يكون لكل منها مجموعة خاصة من الوجهات ذات الصلة. في مثل هذه الحالات، يمكنك بدلاً من ذلك تمرير مجموعة من أرقام تعريف الوجهة إلى الدالة الإنشائية، كما هو موضّح أدناه:

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() من طريقة 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 مع شريط الأدوات، حدد أولاً شريط الأدوات والتنسيق المحيط في نشاطك، كما هو موضح أدناه:

<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 لنشاطك الرئيسي، كما هو موضح أدناه:

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

بدءًا من التنقل 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);
}

بدءًا من التنقل 2.4.0-alpha01، يتم حفظ حالة كل عنصر في القائمة واستعادتها عند استخدام setupWithNavController.

للحصول على مثال شامل يتضمن التنقل السفلي، يُرجى الاطّلاع على نموذج التنقل المتقدم لمكونات بنية Android على GitHub.

الاستماع إلى أحداث التنقّل

يعد التفاعل مع NavController الطريقة الأساسية للتنقل بين الوجهات. تكون NavController مسؤولة عن استبدال محتوى NavHost بالوجهة الجديدة. في كثير من الحالات، تكون عناصر واجهة المستخدم خارج NavHost، مثل شريط التطبيق العلوي أو عناصر التحكّم المستمرة الأخرى في التنقّل، مثل BottomNavigationBar، والتي يجب تعديلها أثناء التنقّل بين الوجهات.

تقدّم 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 التي تتضمّنها ومكوّنات واجهة المستخدم التي تملكها.

مراجع إضافية

لمعرفة المزيد حول التنقل، راجع الموارد الإضافية التالية.

عيّنات

الدروس التطبيقية حول الترميز

مشاركات المدونة

الفيديوهات الطويلة