เชื่อมต่อคอมโพเนนต์ UI กับ NavController โดยใช้ NavigationUI

คอมโพเนนต์การนำทางมีNavigationUI คลาสนี้มีเมธอดแบบคงที่ที่จัดการการนำทางด้วย แถบแอป ลิ้นชักการนำทาง และการนำทางด้านล่าง

แถบแอปด้านบน

แถบแอปด้านบน ให้ตำแหน่งที่สอดคล้องกันที่ด้านบนของแอปแสดงข้อมูล และการทำงานจากหน้าจอปัจจุบัน

วันที่ หน้าจอแสดงแถบแอปด้านบน
รูปที่ 1 หน้าจอแสดงแถบแอปด้านบน

NavigationUI มีวิธีอัปเดตเนื้อหาในตำแหน่งบนสุดโดยอัตโนมัติ แถบแอปขณะที่ผู้ใช้ไปยังส่วนต่างๆ ของแอป ตัวอย่างเช่น NavigationUI ใช้เมธอด ป้ายกำกับปลายทางจากกราฟการนำทางเพื่อเก็บชื่อแอปยอดนิยมไว้ อัปเดตเป็นเวอร์ชันล่าสุดแล้ว

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

เมื่อใช้ NavigationUI กับการใช้งานแถบแอปยอดนิยมที่กล่าวถึงด้านล่าง ป้ายกำกับที่คุณแนบกับปลายทางอาจถูกสร้างโดยอัตโนมัติจาก อาร์กิวเมนต์ที่ระบุไปยังปลายทางโดยใช้รูปแบบ {argName} ใน ป้ายกำกับ

NavigationUI รองรับแถบแอปยอดนิยมประเภทต่อไปนี้

ดูข้อมูลเพิ่มเติมเกี่ยวกับแถบแอปได้ที่ตั้งค่าแถบแอป

การกำหนดค่าแถบแอป

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 สิ่งนี้อาจมีประโยชน์ ตัวอย่างเช่น หากคุณมีกิจกรรมที่ 2 ที่ควรแสดงปุ่ม "ขึ้น" ใน 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 อันดับแรก แถบเครื่องมือมาตรฐานทางด้านซ้าย
            Appbarlayout ที่มีแถบเครื่องมือและแท็บอยู่ด้านขวา
รูปที่ 2 แถบแอป 2 แบบที่แตกต่างกัน ทางด้านซ้าย มาตรฐาน Toolbar ทางด้านขวา AppBarLayout ที่มี Toolbar และแท็บ

หากต้องการใช้ตัวอย่างนี้ภายในส่วนย่อยปลายทางของคุณโดยใช้ NavigationUI ให้กำหนดแถบแอปในเลย์เอาต์ Fragment แต่ละรายการก่อน เริ่มต้นด้วยส่วนย่อยปลายทางที่ใช้แถบเครื่องมือมาตรฐาน

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

ตรรกะการกำหนดค่าการนำทางจะเหมือนกันสำหรับ Fragment ทั้งสองนี้ เว้นแต่ว่าคุณควรโทรหา 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 ยังมีตัวช่วยสำหรับการเชื่อมโยงปลายทางกับ UI ที่ขับเคลื่อนด้วยเมนู คอมโพเนนต์ NavigationUI มีเมธอด Helper 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 เดียวกันโดยอัตโนมัติ

เพิ่มลิ้นชักการนำทาง

ลิ้นชักการนำทางคือแผง UI ที่แสดงเมนูการนำทางหลักของแอป ลิ้นชักจะปรากฏขึ้นเมื่อผู้ใช้แตะไอคอนลิ้นชัก ในแถบแอป หรือเมื่อผู้ใช้ปัดนิ้วจากขอบด้านซ้ายของแอป บนหน้าจอ

วันที่ ลิ้นชักที่เปิดอยู่ที่แสดงเมนูการนำทาง
รูปที่ 3 ลิ้นชักที่เปิดอยู่แสดงการนำทาง เมนู

ไอคอนลิ้นชักปรากฏอยู่บน ปลายทางระดับบนสุดที่ใช้ DrawerLayout

หากต้องการเพิ่มลิ้นชักการนำทาง ให้ประกาศ DrawerLayout เป็นรูท ภายใน DrawerLayout ให้เพิ่มเลย์เอาต์สำหรับเนื้อหา UI หลัก และ อีกมุมมองหนึ่งที่มีเนื้อหาของลิ้นชักการนำทาง

ตัวอย่างเช่น เลย์เอาต์ต่อไปนี้ใช้ DrawerLayout ที่มีมุมมองย่อย 2 มุมมอง ได้แก่ 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 โดยระบุปลายทางใหม่ ในหลายกรณี องค์ประกอบ UI เช่น แถบแอปด้านบน หรือ การควบคุมการนำทางแบบถาวรอื่นๆ เช่น BottomNavigationBar แบบสดกลางแจ้ง ของ NavHost และจะต้องได้รับการอัปเดตขณะไปยังปลายทางต่างๆ

NavController มีอินเทอร์เฟซ OnDestinationChangedListener ที่ เรียกใช้เมื่อปลายทางปัจจุบันของ NavController หรืออาร์กิวเมนต์มีการเปลี่ยนแปลง ผู้ฟังใหม่สามารถลงทะเบียนผ่าน addOnDestinationChangedListener() โปรดทราบว่าเมื่อโทรหา addOnDestinationChangedListener() หาก มีปลายทางปัจจุบันอยู่ จะมีการส่งไปยัง Listener ของคุณทันที

NavigationUI ใช้ OnDestinationChangedListener เพื่อสร้าง UI ทั่วไปเหล่านี้ พิจารณาการนำทางของคอมโพเนนต์ แต่โปรดทราบว่าคุณสามารถใช้ OnDestinationChangedListener เพื่อสร้าง UI หรือธุรกิจที่กำหนดเอง รับรู้ถึงเหตุการณ์การนำทางได้

ตัวอย่างเช่น คุณอาจมีองค์ประกอบ UI ทั่วไปที่คุณตั้งใจจะแสดง พื้นที่บางส่วนของแอป ขณะซ่อนส่วนอื่นๆ ใช้ของคุณเอง OnDestinationChangedListener คุณสามารถเลือกแสดงหรือซ่อน UI เหล่านี้ได้ ตามปลายทางเป้าหมาย ดังที่แสดงในตัวอย่างต่อไปนี้

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

Listener ที่ใช้อาร์กิวเมนต์

อีกวิธีหนึ่งคือ คุณสามารถใช้อาร์กิวเมนต์ที่มีค่าเริ่มต้นอยู่ภายใน กราฟการนำทาง ซึ่งสามารถใช้โดยตัวควบคุม UI ที่เหมาะสม เพื่ออัปเดตสถานะ เช่น แทนที่จะสร้างพื้นฐานตามตรรกะในมิติข้อมูล 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 เรียกใช้ Callback นี้เมื่อปลายทางของการนำทางเปลี่ยนแปลง Activity อัปเดตสถานะหรือการมองเห็นคอมโพเนนต์ UI ได้แล้ว ที่เป็นเจ้าของตามอาร์กิวเมนต์ที่ได้รับใน Callback

ข้อดีอย่างหนึ่งของวิธีนี้คือ Activity เห็นเฉพาะ อาร์กิวเมนต์ในกราฟการนำทางและไม่รู้จัก Fragment แต่ละรายการ บทบาทและความรับผิดชอบ ในทำนองเดียวกัน ส่วนย่อยแต่ละรายการไม่ทราบ เกี่ยวกับ Activity ที่มีและคอมโพเนนต์ UI ที่ URL ดังกล่าวเป็นเจ้าของ

แหล่งข้อมูลเพิ่มเติม

หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการนำทาง โปรดดูแหล่งข้อมูลเพิ่มเติมต่อไปนี้

ตัวอย่าง

Codelab

บล็อกโพสต์

วิดีโอ