Bắt đầu với thành phần Điều hướng

Chủ đề này hướng dẫn bạn cách thiết lập và làm việc với thành phần Điều hướng. Để tìm hiểu khái quát về thành phần Điều hướng, hãy xem Tổng quan về Điều hướng.

Thiết lập môi trường

Để đưa tính năng hỗ trợ Điều hướng vào dự án của bạn, hãy thêm các phần phụ thuộc sau vào tệp build.gradle trong ứng dụng:

Groovy

dependencies {
  def nav_version = "2.5.3"

  // Java language implementation
  implementation "androidx.navigation:navigation-fragment:$nav_version"
  implementation "androidx.navigation:navigation-ui:$nav_version"

  // Kotlin
  implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
  implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

  // Feature module Support
  implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"

  // Testing Navigation
  androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"

  // Jetpack Compose Integration
  implementation "androidx.navigation:navigation-compose:$nav_version"
}

Kotlin

dependencies {
  val nav_version = "2.5.3"

  // Java language implementation
  implementation("androidx.navigation:navigation-fragment:$nav_version")
  implementation("androidx.navigation:navigation-ui:$nav_version")

  // Kotlin
  implementation("androidx.navigation:navigation-fragment-ktx:$nav_version")
  implementation("androidx.navigation:navigation-ui-ktx:$nav_version")

  // Feature module Support
  implementation("androidx.navigation:navigation-dynamic-features-fragment:$nav_version")

  // Testing Navigation
  androidTestImplementation("androidx.navigation:navigation-testing:$nav_version")

  // Jetpack Compose Integration
  implementation("androidx.navigation:navigation-compose:$nav_version")
}

Để biết thông tin về việc thêm các thành phần cấu trúc khác vào dự án, hãy xem phần Thêm các thành phần vào dự án.

Tạo biểu đồ điều hướng

Hoạt động điều hướng diễn ra giữa các đích đến của ứng dụng, nghĩa là mọi nơi trong ứng dụng mà người dùng có thể di chuyển đến. Các đích đến này được kết nối thông qua hành động.

Biểu đồ điều hướng là một tệp tài nguyên chứa tất cả các đích đến và hành động. Biểu đồ thể hiện tất cả đường dẫn điều hướng trong ứng dụng của bạn.

Hình 1 cho thấy bản trình bày bằng hình ảnh của biểu đồ điều hướng cho một ứng dụng mẫu có chứa 6 đích đến được kết nối bằng 5 hành động. Mỗi đích đến được biểu thị bằng một hình thu nhỏ xem trước, các hành động kết nối được biểu thị bằng các mũi tên cho thấy cách người dùng di chuyển từ đích đến này sang đích đến khác.

Hình 1. Biểu đồ điều hướng hiển thị hình ảnh xem trước của 6 đích đến khác nhau được kết nối bằng 5 hành động.
  1. Đích đến là các khu vực nội dung khác nhau trong ứng dụng của bạn.
  2. Hành động là kết nối logic giữa các đích đến thể hiện những đường dẫn mà người dùng có thể chọn.

Để thêm biểu đồ điều hướng vào dự án, hãy làm như sau:

  1. Trong cửa sổ Project (Dự án), hãy nhấp chuột phải vào thư mục res rồi chọn New > Android Resource File (Mới > Tệp tài nguyên Android). Hộp thoại New Resource File (Tệp tài nguyên mới) xuất hiện.
  2. Nhập một tên vào trường File name (Tên tệp), chẳng hạn như "nav_graph".
  3. Chọn Navigation (Điều hướng) từ danh sách thả xuống Resource type (Loại tài nguyên), sau đó nhấp vào OK.

Khi bạn thêm biểu đồ điều hướng đầu tiên, Android Studio sẽ tạo một thư mục tài nguyên navigation trong thư mục res. Thư mục này chứa tệp tài nguyên của biểu đồ điều hướng (chẳng hạn như nav_graph.xml).

Sau khi thêm biểu đồ, Android Studio sẽ mở biểu đồ trong Navigation Editor (Trình chỉnh sửa điều hướng). Trong Navigation Editor (Trình chỉnh sửa điều hướng), bạn có thể chỉnh sửa biểu đồ điều hướng theo cách trực quan hoặc trực tiếp chỉnh sửa tệp XML cơ sở.

Hình 2. Trình chỉnh sửa điều hướng
  1. Destinations panel (Bảng đích đến): Liệt kê máy chủ điều hướng và tất cả các đích đến hiện có trong Graph Editor (Trình chỉnh sửa biểu đồ).
  2. Graph Editor (Trình chỉnh sửa biểu đồ): Chứa bản trình bày bằng hình ảnh của biểu đồ điều hướng. Bạn có thể chuyển đổi giữa thành phần hiển thị Design (Thiết kế) và bản trình bày của tệp XML cơ sở trong thành phần hiển thị Text (Văn bản).
  3. Attributes (Thuộc tính): Hiển thị các thuộc tính cho mục đang được chọn trong biểu đồ điều hướng.

Nhấp vào thẻ Text (Văn bản) để xem tệp XML tương ứng, tệp này sẽ trông giống đoạn mã sau:

<?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/nav_graph">

</navigation>

Phần tử <navigation> là phần tử gốc của biểu đồ điều hướng. Khi thêm các đích đến và hành động kết nối vào biểu đồ, bạn có thể thấy các phần tử <destination><action> tương ứng tại đây dưới dạng các phần tử con. Nếu bạn có các biểu đồ lồng nhau, thì chúng sẽ xuất hiện dưới dạng các phần tử <navigation> con.

Thêm NavHost vào một hoạt động

Máy chủ điều hướng là một trong những phần chính của thành phần Điều hướng. Máy chủ điều hướng là một vùng chứa trống, trong đó các đích đến được hoán đổi khi người dùng di chuyển trong ứng dụng của bạn.

Một máy chủ điều hướng phải bắt nguồn từ NavHost. Hoạt động triển khai NavHost mặc định của thành phần Điều hướng, NavHostFragment, xử lý việc hoán đổi các đích đến của mảnh.

Thêm NavHostFragment thông qua XML

Ví dụ XML bên dưới cho thấy NavHostFragment như một phần trong hoạt động chính của một ứng dụng:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.appcompat.widget.Toolbar
        .../>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"

        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        .../>

</androidx.constraintlayout.widget.ConstraintLayout>

Xin lưu ý những điều sau:

  • Thuộc tính android:name chứa tên lớp của hoạt động triển khai NavHost.
  • Thuộc tính app:navGraph liên kết NavHostFragment với một biểu đồ điều hướng. Biểu đồ điều hướng chỉ định tất cả các đích đến trong NavHostFragment này mà người dùng có thể di chuyển đến.
  • Thuộc tính app:defaultNavHost="true" đảm bảo rằng NavHostFragment sẽ chặn nút Quay lại của hệ thống. Xin lưu ý rằng bạn chỉ có thể đặt một NavHost là mặc định. Nếu có nhiều máy chủ trong cùng một bố cục (ví dụ: bố cục hai ngăn), hãy nhớ chỉ định một NavHost mặc định duy nhất.

Bạn cũng có thể sử dụng Layout Editor để thêm NavHostFragment vào một hoạt động theo cách sau đây:

  1. Trong danh sách các tệp dự án, hãy nhấp đúp vào tệp XML bố cục của hoạt động để mở tệp đó trong Trình chỉnh sửa bố cục.
  2. Trong ngăn Palette (Bảng thành phần hiển thị), hãy chọn danh mục Containers (Vùng chứa) hoặc tìm "NavHostFragment".
  3. Kéo thành phần hiển thị NavHostFragment vào hoạt động của bạn.
  4. Tiếp theo, trong hộp thoại Navigation Graphs (Biểu đồ điều hướng) hiển thị, hãy chọn biểu đồ điều hướng tương ứng để liên kết với NavHostFragment này, sau đó nhấp vào OK.

Thêm đích đến vào biểu đồ điều hướng

Bạn có thể tạo đích đến từ một mảnh hoặc hoạt động hiện có. Bạn cũng có thể dùng Navigation Editor (Trình chỉnh sửa điều hướng) để tạo đích đến mới hoặc tạo phần giữ chỗ rồi sau này thay thế bằng một mảnh hoặc hoạt động.

Trong ví dụ này, hãy tạo một đích đến mới. Để thêm đích đến mới bằng Trình chỉnh sửa điều hướng, hãy làm như sau:

  1. Trong Navigation Editor (Trình chỉnh sửa điều hướng), hãy nhấp vào biểu tượng Đích đến mới , sau đó nhấp vào Create new destination (Tạo đích đến mới).
  2. Tạo mảnh trong hộp thoại New Android Component (Thành phần Android mới). Để biết thêm thông tin về mảnh, hãy xem tài liệu về mảnh.

Quay lại Navigation Editor (Trình chỉnh sửa điều hướng), hãy lưu ý rằng Android Studio đã thêm đích đến này vào biểu đồ.

Hình 3 cho thấy ví dụ về một đích đến và một đích đến của phần giữ chỗ.

Hình 3. Một đích đến và một phần giữ chỗ

Để biết thêm các cách bổ sung đích đến vào biểu đồ điều hướng, hãy xem phần Tạo đích đến.

Phân tích các thành phần của một đích đến

Nhấp để chọn một đích đến, và hãy lưu ý các thuộc tính sau trong bảng Attributes (Thuộc tính):

  • Trường Type (Loại) cho biết đích đến được triển khai dưới dạng mảnh, hoạt động hay lớp tuỳ chỉnh khác trong mã nguồn.
  • Trường Label (Nhãn) chứa tên của đích đến mà người dùng có thể đọc được. Trường này có thể hiển thị trên giao diện người dùng – ví dụ: nếu bạn kết nối NavGraph với một Toolbar bằng setupWithNavController(). Do đó, bạn nên sử dụng chuỗi tài nguyên cho giá trị này.
  • Trường ID (Mã) chứa mã của đích đến dùng để tham chiếu đến đích đến trong mã.
  • Trình đơn thả xuống Class (Lớp) hiển thị tên của lớp đã liên kết với đích đến. Bạn có thể nhấp vào trình đơn thả xuống này để thay đổi lớp đã liên kết thành một loại đích đến khác.

Nhấp vào thẻ Text (Văn bản) để hiển thị thành phần hiển thị XML của biểu đồ điều hướng. XML chứa các thuộc tính id, name, labellayout giống nhau cho đích đến, như hiển thị dưới đây:

<?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"
    app:startDestination="@id/blankFragment">
    <fragment
        android:id="@+id/blankFragment"
        android:name="com.example.cashdog.cashdog.BlankFragment"
        android:label="@string/label_blank"
        tools:layout="@layout/fragment_blank" />
</navigation>

Chỉ định một màn hình làm đích đến bắt đầu

Đích bắt đầu là màn hình đầu tiên người dùng nhìn thấy khi mở ứng dụng và là màn hình cuối cùng mà người dùng nhìn thấy khi thoát ứng dụng. Navigation Editor (Trình chỉnh sửa điều hướng) sử dụng biểu tượng ngôi nhà để biểu thị đích bắt đầu.

Khi đã có tất cả các đích đến, bạn có thể chọn một đích đến bắt đầu theo cách sau đây:

  1. Trong thẻ Design (Thiết kế), hãy nhấp để đánh dấu một đích đến.

  2. Nhấp vào nút Assign start destination (Chỉ định đích đến bắt đầu) . Hoặc, bạn có thể nhấp chuột phải vào đích đến và nhấp vào Set as Start Destination (Đặt làm đích đến bắt đầu).

Kết nối các đích đến

Hành động là kết nối logic giữa các đích đến. Hành động được biểu thị bằng mũi tên trong biểu đồ điều hướng. Hành động thường kết nối đích đến này với đích đến khác, mặc dù bạn cũng có thể tạo các hành động chung đưa bạn đến một đích đến cụ thể từ bất kỳ vị trí nào trong ứng dụng.

Bằng hành động, bạn đưa ra nhiều đường dẫn mà người dùng có thể chọn thông qua ứng dụng của bạn. Xin lưu ý rằng để thực sự di chuyển đến các đích đến, bạn vẫn cần viết mã để thực hiện điều hướng. Điều này sẽ được đề cập sau trong phần Chuyển đến một đích đến trong chủ đề này.

Bạn có thể sử dụng Trình chỉnh sửa điều hướng để kết nối hai đích đến theo cách sau đây:

  1. Trong thẻ Design (Thiết kế), hãy di chuột qua phía bên phải của đích đến mà bạn muốn người dùng di chuyển từ đó. Một vòng tròn sẽ xuất hiện phía bên phải của đích đến, như trong hình 4.

    Hình 4. Một đích đến có vòng kết nối hành động
  2. Nhấp và kéo con trỏ đến đích đến mà bạn muốn người dùng di chuyển đến rồi thả ra. Đường kẻ hình thành giữa hai đích đến biểu thị một hành động, như minh hoạ trong hình 5.

    Hình 5. Kết nối các đích đến với một hành động
  3. Nhấp vào mũi tên để làm nổi bật hành động. Các thuộc tính sau xuất hiện trong bảng Attributes (Thuộc tính):

    • Trường Type (Loại) chứa "Action" (Hành động).
    • Trường ID (Mã) chứa mã cho hành động.
    • Trường Destination (Đích đến) chứa mã cho mảnh hoặc hoạt động đích đến.
  4. Nhấp vào thẻ Text (Văn bản) để chuyển sang khung hiển thị XML. Một phần tử hành động hiện đã được thêm vào đích đến nguồn. Hành động có một mã và một thuộc tính đích đến chứa mã đích đến tiếp theo, như trong ví dụ dưới đây:

    <?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"
        app:startDestination="@id/blankFragment">
        <fragment
            android:id="@+id/blankFragment"
            android:name="com.example.cashdog.cashdog.BlankFragment"
            android:label="@string/label_blank"
            tools:layout="@layout/fragment_blank" >
            <action
                android:id="@+id/action_blankFragment_to_blankFragment2"
                app:destination="@id/blankFragment2" />
        </fragment>
        <fragment
            android:id="@+id/blankFragment2"
            android:name="com.example.cashdog.cashdog.BlankFragment2"
            android:label="@string/label_blank_2"
            tools:layout="@layout/fragment_blank_fragment2" />
    </navigation>
    

Trong biểu đồ điều hướng, các hành động được biểu thị bằng các phần tử <action>. Ở mức tối thiểu, một hành động sẽ chứa mã riêng và mã của đích đến mà người dùng sẽ được chuyển đến.

Việc chuyển đến một đích đến được thực hiện thông qua NavController, một đối tượng quản lý hoạt động điều hướng ứng dụng trong một NavHost. Mỗi NavHost sẽ có NavController tương ứng riêng. Bạn có thể truy xuất một NavController bằng một trong các phương thức sau:

Kotlin:

Java:

Khi bạn tạo NavHostFragment bằng FragmentContainerView hoặc nếu thêm NavHostFragment vào hoạt động theo cách thủ công qua một FragmentTransaction, việc thử truy xuất NavController trong onCreate() của một Hoạt động thông qua Navigation.findNavController(Activity, @IdRes int) sẽ không thành công. Thay vào đó, bạn nên truy xuất NavController trực tiếp từ NavHostFragment.

Kotlin

val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController

Java

NavHostFragment navHostFragment =
        (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
NavController navController = navHostFragment.getNavController();

Đảm bảo an toàn kiểu bằng Safe Args

Bạn nên di chuyển giữa các đích đến bằng trình bổ trợ Safe Args Gradle. Trình bổ trợ này tạo các lớp đối tượng và trình tạo đơn giản cho phép truyền đối số và điều hướng theo loại an toàn giữa các đích đến.

Để thêm Safe Args vào dự án, hãy đưa classpath sau vào tệp build.gradle cấp cao nhất của bạn:

Groovy

buildscript {
    repositories {
        google()
    }
    dependencies {
        def nav_version = "2.5.3"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

Kotlin

buildscript {
    repositories {
        google()
    }
    dependencies {
        val nav_version = "2.5.3"
        classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version")
    }
}

Bạn cũng phải áp dụng 1 trong 2 trình bổ trợ có sẵn.

Để tạo mã ngôn ngữ Java phù hợp với mô-đun Java và Kotlin, hãy thêm dòng này vào tệp build.gradle của ứng dụng hoặc mô-đun:

Groovy

plugins {
  id 'androidx.navigation.safeargs'
}

Kotlin

plugins {
    id("androidx.navigation.safeargs")
}

Ngoài ra, để tạo mã Kotlin phù hợp với các mô-đun chỉ Kotlin, hãy thêm:

Groovy

plugins {
  id 'androidx.navigation.safeargs.kotlin'
}

Kotlin

plugins {
    id("androidx.navigation.safeargs.kotlin")
}

Bạn phải có android.useAndroidX=true trong tệp gradle.properties theo hướng dẫn Di chuyển sang AndroidX.

Sau khi bạn bật Safe Args, trình bổ trợ sẽ tạo mã chứa các lớp và phương thức cho mỗi hành động bạn đã quy định. Đối với mỗi hành động, Safe Args cũng tạo một lớp cho mỗi đích đến ban đầu, là đích đến mà hành động xuất phát từ đó. Tên lớp được tạo là sự kết hợp giữa tên lớp đích đến ban đầu và từ "Directions" (Đường đi). Ví dụ: nếu đích đến có tên là SpecifyAmountFragment, lớp được tạo sẽ có tên là SpecifyAmountFragmentDirections. Lớp được tạo chứa một phương thức tĩnh cho mỗi hành động đã quy định trong đích đến ban đầu. Phương thức này lấy mọi tham số hành động đã quy định làm đối số và trả về một đối tượng NavDirections mà bạn có thể truyền đến navigate().

Ví dụ: giả sử chúng ta có biểu đồ điều hướng với một hành động kết nối đích đến ban đầu là SpecifyAmountFragment với đích đến nhận là ConfirmationFragment.

Safe Args tạo một lớp SpecifyAmountFragmentDirections bằng một phương thức duy nhất là actionSpecifyAmountFragmentToConfirmationFragment(), phương thức này trả về đối tượng NavDirections. Sau đó, đối tượng NavDirections được trả về này có thể được truyền trực tiếp đến navigate(), như trong ví dụ sau:

Kotlin

override fun onClick(view: View) {
    val action =
        SpecifyAmountFragmentDirections
            .actionSpecifyAmountFragmentToConfirmationFragment()
    view.findNavController().navigate(action)
}

Java

@Override
public void onClick(View view) {
    NavDirections action =
        SpecifyAmountFragmentDirections
            .actionSpecifyAmountFragmentToConfirmationFragment();
    Navigation.findNavController(view).navigate(action);
}

Để biết thêm thông tin về việc truyền dữ liệu giữa các đích đến bằng Safe Args, hãy xem phần Sử dụng Safe Args để truyền dữ liệu với an toàn kiểu.

Thông tin khác

Nếu gặp bất kỳ vấn đề nào với Điều hướng, hãy gửi phản hồi thông qua một trong những kênh sau:

Để hiểu cách cung cấp các thông tin hữu ích nhất trong báo cáo lỗi hãy xem các đường liên kết sau: