Kết nối các thành phần trên giao diện người dùng với NavController bằng NavigationUI

Thành phần Điều hướng bao gồm một lớp NavigationUI. Lớp này chứa các phương thức tĩnh giúp quản lý cách điều hướng bằng thanh ứng dụng ở trên cùng, ngăn điều hướng và trình đơn điều hướng ở dưới cùng.

Thanh ứng dụng trên cùng

Thanh ứng dụng trên cùng (top app bar) cung cấp một vị trí nhất quán theo đầu ứng dụng để hiển thị thông tin và các hành động trên màn hình hiện tại.

màn hình cho thấy một thanh ứng dụng trên cùng
Hình 1. Một màn hình cho thấy một thanh ứng dụng trên cùng.

NavigationUI chứa các phương thức tự động cập nhật nội dung trên thanh ứng dụng ở trên cùng khi người dùng di chuyển qua ứng dụng. Ví dụ: NavigationUI sử dụng nhãn đích đến trên biểu đồ điều hướng để luôn cập nhật tiêu đề của thanh ứng dụng ở trên cùng.

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

Khi sử dụng NavigationUI cùng với cách triển khai thanh ứng dụng ở trên cùng như thảo luận dưới đây, nhãn bạn đính kèm với đích đến có thể tự động được điền bằng các đối số cung cấp cho đích đến đó thông qua định dạng của {argName} trong nhãn.

NavigationUI hỗ trợ các loại thanh ứng dụng trên cùng sau đây:

Để biết thêm thông tin về thanh ứng dụng, hãy xem nội dung Thiết lập thanh ứng dụng.

AppBarConfiguration

NavigationUI sử dụng đối tượng AppBarConfiguration để quản lý hoạt động của nút Điều hướng ở góc trên bên trái khu vực hiển thị của ứng dụng. Hành vi của nút Điều hướng thay đổi tuỳ thuộc vào việc người dùng có đang ở đích cấp cao nhất hay không.

Đích đến (destination) cấp cao nhất là đích gốc hoặc cấp cao nhất trong một tập hợp các đích đến liên quan theo hệ phân cấp. Đích cấp cao nhất không hiển thị nút Mũi tên lên trong thanh ứng dụng trên cùng vì không có đích cấp cao hơn. Theo mặc định, đích đến bắt đầu của ứng dụng là đích đến cấp cao nhất duy nhất.

Khi người dùng ở một đích đến cấp cao nhất, nút Navigation (Điều hướng) sẽ trở thành biểu tượng ngăn nếu đích đến đó sử dụng DrawerLayout. Nếu đích không sử dụng DrawerLayout, nút Điều hướng sẽ bị ẩn. Khi người dùng đang ở đích khác, nút Điều hướng sẽ xuất hiện dưới dạng nút Mũi tên lên . Để định cấu hình nút Navigation (Điều hướng) chỉ sử dụng đích đến bắt đầu làm đích đến cấp cao nhất, hãy tạo một đối tượng AppBarConfiguration rồi truyền vào biểu đồ điều hướng tương ứng, như minh hoạ dưới đây:

Kotlin

val appBarConfiguration = AppBarConfiguration(navController.graph)

Java

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

Trong một số trường hợp, bạn có thể phải xác định nhiều đích cấp cao nhất thay vì sử dụng đích xuất phát mặc định. Việc dùng BottomNavigationView là một trường hợp sử dụng phổ biến cho trường hợp này, trong đó bạn có thể có các màn hình đồng cấp không liên quan theo hệ phân cấp và mỗi màn hình có thể có một tập hợp các đích đến liên quan riêng. Đối với các trường hợp như vậy, bạn có thể truyền một tập hợp mã nhận dạng đích đến vào hàm khởi tạo, như minh hoạ dưới đây:

Kotlin

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

Java

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

Tạo Thanh công cụ

Để Tạo thanh công cụ (Toolbar) bằng NavigationUI, trước tiên, hãy xác định thanh đps trong hoạt động chính của bạn, như minh hoạ dưới đây:

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

Tiếp theo, hãy gọi setupWithNavController() qua phương thức onCreate() của hoạt động chính, như minh hoạ trong ví dụ dưới đây:

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

Để định cấu hình sao cho nút Navigation (Điều hướng) xuất hiện dưới dạng nút Up (Mũi tên lên) cho mọi đích đến, hãy truyền một tập hợp mã nhận dạng đích đến trống vào các đích đến cấp cao nhất khi tạo AppBarConfiguration. Ví dụ: điều này có thể hữu ích trong trường hợp bạn có hoạt động thứ hai và cần hiển thị nút Up (Mũi tên lên) trong Toolbar trên mọi đích đến. Điều này cho phép người dùng quay lại hoạt động mẹ khi không có đích nào khác trên ngăn xếp lui Bạn có thể sử dụng setFallbackOnNavigateUpListener() để kiểm soát hành vi dự phòng cho trường hợp navigateUp() không làm gì khác, như thể hiện trong ví dụ sau:

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

Bao gồm CollapsingToolbarLayout

Để đưa CollapsingToolbarLayout vào Thanh công cụ, trước tiên, hãy xác định Thanh công cụ và bố cục xung quanh trong hoạt động của bạn, như thể hiện dưới đây:

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

Tiếp theo, hãy gọi setupWithNavController() qua phương thức onCreate của hoạt động chính như thể hiện dưới đây:

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

Thanh thao tác

Để hỗ trợ chức năng di chuyển cho thanh thao tác (action bar) mặc định, hãy gọi setupActionBarWithNavController() qua phương thức onCreate() của hoạt động chính như thể hiện dưới đây: Xin lưu ý rằng bạn cần khai báo AppBarConfiguration bên ngoài onCreate() vì bạn cũng sử dụng chế độ này khi ghi đè 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);
}

Tiếp theo, hãy ghi đè onSupportNavigateUp() để xử lý xử lý di chuyển Lên:

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

Hỗ trợ các biến thể của thanh ứng dụng

Bạn nên thêm thanh ứng dụng ở trên cùng vào hoạt động khi bố cục của thanh ứng dụng cho mỗi đích đến trong ứng dụng là giống nhau. Tuy nhiên, nếu thanh ứng dụng ở trên cùng có sự thay đổi đáng kể giữa các đích đến, hãy cân nhắc việc xoá thanh ứng dụng ở trên cùng khỏi hoạt động rồi khai báo thanh đó trong từng mảnh đích đến.

Ví dụ: một trong các đích đến có thể sử dụng Toolbar tiêu chuẩn, trong khi một đích đến khác sử dụng AppBarLayout để tạo thanh ứng dụng phức tạp hơn với các thẻ, như minh hoạ trong hình 2.

two top app bar variations; a standard toolbar on the left, and an appbarlayout with a toolbar and tabs on the right (2 biến thể thanh ứng dụng ở trên cùng; 1 thanh công cụ chuẩn ở bên trái và 1 appbarlayout với thanh công cụ và các thẻ ở bên phải)
Hình 2. Hai biến thể thanh ứng dụng. Ở bên trái, Toolbar tiêu chuẩn. Ở bên phải, AppBarLayout chứa Toolbar và các thẻ.

Để triển khai ví dụ này trong các mảnh đích đến bằng cách sử dụng NavigationUI, trước tiên, hãy khai báo thanh ứng dụng trong mỗi bố cục mảnh, bắt đầu từ mảnh đích đến sử dụng thanh công cụ chuẩn:

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

Tiếp theo, hãy xác định mảnh đích sử dụng thanh ứng dụng có các thẻ:

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

Logic của cấu hình điều hướng là như nhau đối với cả hai mảnh này, ngoại trừ việc bạn nên gọi setupWithNavController() ngay từ phương thức onViewCreated() của từng mảnh, thay vì khởi chạy các mảnh trong hoạt động:

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

Gắn đích với mục trong trình đơn

NavigationUI cũng cung cấp các trình trợ giúp để liên kết các đích với thành phần giao diện người dùng theo trình đơn. NavigationUI chứa một phương thức trợ giúp onNavDestinationSelected(), sử dụng MenuItem cùng với NavController lưu trữ đích đến liên kết. Nếu id của MenuItem khớp với id của đích, thì NavController có thể điều hướng đến đích đó.

Ví dụ: các đoạn mã XML dưới đây xác định một mục trong trình đơn và một đích đến có id phổ biến là 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>

Ví dụ: Nếu bạn thêm trình đơn qua onCreateOptionsMenu() của Hoạt động, bạn có thể liên kết các mục trong trình đơn với đích đến bằng cách ghi đè onOptionsItemSelected() của Hoạt động để gọi onNavDestinationSelected(), như minh hoạ trong ví dụ dưới đây:

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

Bây giờ, khi người dùng nhấp vào mục trong trình đơn details_page_fragment, ứng dụng sẽ tự động chuyển đến đích tương ứng bằng cùng một id.

Thêm ngăn điều hướng

Ngăn điều hướng (navigation drawer) là một bảng điều khiển trên giao diện người dùng cho thấy trình đơn điều hướng chính của ứng dụng. Ngăn này sẽ xuất hiện khi người dùng nhấn vào biểu tượng ngăn trong thanh ứng dụng hoặc khi người dùng vuốt từ mép trái màn hình.

một ngăn mở cho thấy trình đơn điều hướng
Hình 3. Một ngăn mở cho thấy trình đơn điều hướng.

Biểu tượng ngăn kéo xuất hiện trên tất cả đích cấp cao nhất sử dụng DrawerLayout.

Để thêm một ngăn điều hướng, trước tiên, hãy khai báo DrawerLayout làm thành phần hiển thị gốc. Bên trong DrawerLayout, hãy thêm một bố cục cho nội dung chính trên giao diện người dùng và một thành phần hiển thị khác chứa nội dung của ngăn điều hướng.

Ví dụ: bố cục sau sử dụng DrawerLayout với hai thành phần hiển thị con: một NavHostFragment để chứa nội dung chính và một NavigationView cho nội dung của ngăn điều hướng.

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

Tiếp theo, hãy kết nối DrawerLayout với biểu đồ điều hướng bằng cách truyền biểu đồ đó vào AppBarConfiguration, như minh hoạ trong ví dụ dưới đây:

Kotlin

val appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)

Java

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

Tiếp theo, trong lớp hoạt động chính, hãy gọi setupWithNavController() qua phương thức onCreate() của hoạt động chính như thể hiện dưới đây:

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

Kể từ Navigation 2.4.0-alpha01, trạng thái của từng mục trong trình đơn sẽ được lưu và khôi phục khi bạn sử dụng setupWithNavController.

Thanh điều hướng dưới cùng

NavigationUI cũng có thể xử lý thao tác ở dưới cùng. Khi người dùng chọn một mục trong trình đơn, NavController sẽ gọi onNavDestinationSelected() và tự động cập nhật mục đã chọn trong thanh điều hướng dưới cùng (bottom navigation bar).

thanh điều hướng ở dưới cùng
Hình 4. Một thanh điều hướng ở dưới cùng.

Để tạo thanh điều hướng dưới cùng trong ứng dụng, trước tiên, hãy xác định thanh đó trong hoạt động chính của bạn, như thể hiện dưới đây.

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

Tiếp theo, trong lớp hoạt động chính, hãy gọi setupWithNavController() qua phương thức onCreate() của hoạt động chính như thể hiện dưới đây:

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

Kể từ Navigation 2.4.0-alpha01, trạng thái của từng mục trong trình đơn sẽ được lưu và khôi phục khi bạn sử dụng setupWithNavController.

Để biết ví dụ toàn diện về cách cung cấp thanh điều hướng ở dưới cùng, hãy xem, nội dung Mẫu điều hướng nâng cao cho bộ thành phần cấu trúc Android trên GitHub.

Nghe sự kiện điều hướng

Tương tác với NavController là phương thức chính để di chuyển giữa các đích. NavController có trách nhiệm thay thế nội dung của NavHost bằng đích đến mới. Trong nhiều trường hợp, các thành phần trên giao diện người dùng (chẳng hạn như thanh ứng dụng ở trên cùng hoặc các nút điều khiển thao tác cố định khác như BottomNavigationBar) nằm bên ngoài NavHost và cần được cập nhật khi bạn di chuyển giữa các đích đến.

NavController cung cấp giao diện OnDestinationChangedListener được gọi khi đích hiện tại của NavController hoặc đối số của thành phần này thay đổi. Bạn có thể đăng ký trình nghe mới thông qua phương thức addOnDestinationChangedListener(). Lưu ý rằng khi gọi addOnDestinationChangedListener(), nếu đích hiện tại đang tồn tại, đích đó sẽ được gửi ngay đến trình nghe

NavigationUI sử dụng OnDestinationChangedListener để làm cho các thành phần giao diện người dùng phổ biến này nhận biết được thành phần điều hướng. Tuy nhiên, hãy lưu ý rằng bạn cũng có thể sử dụng riêng OnDestinationChangedListener để giúp thành phần giao diện người dùng tuỳ chỉnh hoặc logic doanh nghiệp nhận biết được sự kiện điều hướng.

Ví dụ: có thể bạn có các thành phần giao diện người dùng phổ biến mà bạn dự định hiển thị trong một số khu vực của ứng dụng trong khi ẩn các thành phần đó trong các khu vực khác. Khi sử dụng OnDestinationChangedListener của riêng mình, bạn có thể hiện hoặc ẩn các thành phần giao diện người dùng này một cách có chọn lọc dựa trên đích, như trong ví dụ sau:

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

Trình nghe dựa trên đối số

Thay vào đó, bạn cũng có thể sử dụng các đối số có giá trị mặc định trong biểu đồ điều hướng. Trình điều khiển giao diện người dùng thích hợp có thể sử dụng biểu đồ này để cập nhật trạng thái. Ví dụ: thay vì dựa vào logic trong OnDestinationChangedListener trên mã nhận dạng đích như trong ví dụ trước, chúng ta có thể tạo một đối số trong 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>

Bạn không được dùng đối số này khi di chuyển tới đích đến mà thay vào đó là để đính kèm thông tin bổ sung vào đích đến bằng cách sử dụng defaultValue. Trong trường hợp này, giá trị cho biết liệu thanh ứng dụng có nên hiện ra khi ở trên đích đến này hay không.

Bây giờ, chúng ta có thể thêm OnDestinationChangedListener trong 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 gọi lệnh gọi lại này bất cứ khi nào đích điều hướng thay đổi. Activity nay có thể cập nhật trạng thái hoặc chế độ hiển thị của các thành phần giao diện người dùng mà ứng dụng sở hữu dựa trên các đối số nhận được trong lệnh gọi lại.

Một ưu điểm của phương pháp này là Activity chỉ xem được các đối số trong biểu đồ điều hướng mà không biết từng vai trò và trách nhiệm Fragment riêng lẻ. Tương tự, từng phần riêng lẻ không biết về Activity chứa và các thành phần giao diện người dùng mà phần đó sở hữu.

Tài nguyên khác

Để tìm hiểu thêm về hoạt động điều hướng, hãy xem một số tài nguyên bổ sung sau đây.

Mẫu

Lớp học lập trình

Bài đăng trên blog

Video