開始使用導覽元件

本主題將說明如何設定及使用導覽元件。如需導覽元件的概略總覽,請參閱「導覽總覽」。

設定環境

如要在專案中加入導覽支援,請將以下依附元件加入應用程式的 build.gradle 檔案:

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

如要進一步瞭解如何將其他架構元件新增至專案,請參閱「將元件新增至專案」。

建立導覽圖表

應用程式的「到達網頁」之間會顯示導覽,也就是使用者在應用程式中可導覽的任何位置。這些到達網頁會透過「操作」連結

「導覽圖表」是包含所有到達網頁和操作的資源檔案。這張圖表代表您應用程式的所有瀏覽路徑。

圖 1 中的範例應用程式以視覺化方式呈現圖表,其中包含由五個操作所連結的六個到達網頁。每個到達網頁都以預覽縮圖表示,而連結操作會以箭頭表示使用者從某個到達網頁前往另一個到達網頁的方式。

圖 1 此導覽圖顯示透過 5 個操作連結 6 個不同到達網頁的預覽畫面。
  1. 「到達網頁」是應用程式中不同的內容區域
  2. 「操作」是到達網頁之間的邏輯連結,代表使用者能夠採取的路徑

如要在專案中新增導覽圖表,請按照下列步驟操作:

  1. 在「Project」(專案) 視窗的 res 目錄中,按一下滑鼠右鍵並依序選取「New」(新增) >「Android 資源檔案」(Android Resource File)。畫面上會顯示「New Resource File」(新增資源檔案) 對話方塊。
  2. 在「File Name」(檔案名稱) 欄位中輸入名稱,例如「nav_Graph」
  3. 從「Resource Type」(資源類型) 下拉式清單中選取「Navigation」(導覽),然後按一下「OK」(確定)

新增第一個導覽圖時,Android Studio 會在 res 目錄中建立 navigation 資源目錄。這個目錄包含您的導覽圖資源檔案 (例如 nav_graph.xml)。

新增圖表後,Android Studio 會在導覽編輯器中開啟圖表。在導覽編輯器中,您可以直接編輯導覽圖表或直接編輯基礎 XML。

圖 2. 導覽編輯器
  1. 到達網頁面板:列出導覽圖表,以及目前圖形編輯器中的所有到達網頁。
  2. 圖表編輯器:包含導覽圖表的示意圖。您可以在「Text」(文字) 檢視畫面中切換使用「Design」(設計) 檢視畫面和基礎 XML 表示法。
  3. 屬性:顯示導覽圖表中目前選取項目的屬性。

按一下「Text」(文字) 分頁標籤,即可查看對應的 XML,類似下列程式碼片段:

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

<navigation> 元素是導覽圖表的根元素。在圖表中加入到達網頁和連結操作時,您可以在這裡查看對應的 <destination><action> 元素做為子項元素。如果您有巢狀圖表,則這些圖表會顯示為子項 <navigation> 元素。

將 NavHost 新增至活動

導覽元件的其中一個核心就是「導覽主機」。導覽主機是空白的容器,當使用者瀏覽您的應用程式時,到達網頁會改變並縮小。

導覽主機必須來自 NavHost。導覽元件的預設 NavHost 實作 (NavHostFragment) 會處理片段到達網頁切換。

透過 XML 新增 NavHostFragment

以下 XML 範例顯示了 NavHostFragment 做為應用程式主要活動的一部分:

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

注意事項:

  • android:name 屬性包含您 NavHost 實作的類別名稱。
  • app:navGraph 屬性會將 NavHostFragment 與導覽圖表建立關聯。導覽圖表會指定使用者能瀏覽這個 NavHostFragment 中的所有到達網頁。
  • app:defaultNavHost="true" 屬性可確保 NavHostFragment 攔截系統返回按鈕。請注意,只有一個 NavHost 可以設為預設。如果您在同一個版面配置中有多個主機 (例如雙窗格版面配置),請務必只指定一個預設 NavHost

您也可以透過版面配置編輯器,在活動中新增 NavHostFragment,如下所示:

  1. 在專案檔案清單中,按兩下活動的版面配置 XML 檔案,即可在版面配置編輯器中開啟。
  2. 在「Palette」(區塊面板) 窗格中,選擇「Containers」(容器) 類別,或直接搜尋「NavHostFragment」
  3. NavHostFragment 資料檢視拖曳到你的活動上。
  4. 接著,在隨即顯示的「Navigation Graphs」(導覽圖表) 對話方塊中,選擇與這個 NavHostFragment 建立關聯的對應導覽圖表,然後按一下「OK」(確定)

在導覽圖表中新增到達網頁

您可以使用現有的片段或活動建立到達網頁,也可以使用導覽編輯器建立新的到達網頁,或是建立預留位置,以便日後取代片段或活動。

在這個範例中,我們來建立新到達網頁。如要使用導覽編輯器新增到達網頁,請執行下列步驟:

  1. 在導覽編輯器中,按一下「新增到達網頁」圖示 ,然後按一下「Creat New Destination」(建立新的到達網頁)
  2. 在隨即顯示的「New Android Component」(新增 Android 元件) 對話方塊中建立您的片段。若要進一步瞭解片段,請參閱片段說明文件

返回導覽編輯器,請注意 Android Studio 已將這個到達網頁新增至圖表。

圖 3 是到達網頁和預留位置到達網頁的範例。

圖 3 到達網頁和預留位置

如要瞭解如何將其他到達網頁新增至導覽圖表,請參閱「建立到達網頁」一文。

到達網頁分析

按一下到達網頁加以選取,並注意「Attributes」(屬性) 面板中的下列屬性

  • 「Type」(類型) 欄位會表示到達網頁在原始碼中是以片段、活動或其他自訂類別進行實作
  • 「Label」(標籤) 欄位包含到達網頁的使用者可讀取名稱。這可能會顯示在使用者介面中,舉例來說,如果您使用 setupWithNavController() 連結 NavGraphToolbar,就可能會這樣。因此,建議您使用這個值的資源字串。
  • 「ID」欄位包含到達網頁的 ID,用來在程式碼中參照到達網頁
  • 「Class」(類別) 下拉式選單會顯示與到達網頁相關聯的類別名稱。您可以點選這個下拉式選單,將相關類別變更為其他到達網頁類型。

按一下「Text」(文字) 分頁標籤,顯示導覽圖表的 XML 檢視畫面。XML 含有相同的到達網頁 idnamelabellayout 屬性,如下所示:

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

將畫面指定為起始到達網頁

「起始到達網頁」是使用者開啟應用程式時看到的第一個畫面,也是使用者離開應用程式時最後看到的畫面。導覽編輯器會使用房屋圖示 來表示起始到達網頁。

所有到達網頁都設定完畢後,您可以按照下列步驟選擇起始到達網頁:

  1. 在「Design」(設計) 分頁中,按一下到達網頁即可醒目顯示

  2. 按一下「Assign Start Destination」(指派起始到達網頁) 按鈕 。或者,您也可以在到達網頁上按一下滑鼠右鍵,然後按一下「Set as Start Destination」(設為起始到達網頁)

連結到達網頁

「操作」是指到達網頁之間的邏輯連結。在導覽圖表中,這類操作會以箭頭表示。操作通常會將到達網頁連結至其他到達網頁,但您也可以建立通用操作,從應用程式的任何位置前往特定到達網頁。

使用操作,您代表了使用者可透過應用程式瀏覽的不同路徑。請注意,如要前往到達網頁,您還是必須編寫程式碼來執行導航。這個主題將於本文稍後的「前往到達網頁」一節中說明。

您可以使用導覽編輯器連結兩個到達網頁,方法如下:

  1. 在「Design」(設計) 分頁中,將遊標懸停在要讓使用者前往的到達網頁右側。圓圈會顯示在到達網頁的右側,如圖 4 所示。

    圖 4.到達網頁含有操作連線圈
  2. 將滑鼠遊標拖曳至您要讓使用者瀏覽及使用的到達網頁。兩個到達網頁之間的結果代表一個操作,如圖 5 所示。

    圖 5 將操作連結至到達網頁
  3. 按一下箭頭醒目顯示操作。下列屬性會顯示在「屬性」面板中

    • 「Type」(類型) 欄位包含「Action」(操作)
    • 「ID」欄位包含操作的 ID
    • 「Destination」(到達網頁) 欄位包含到達網頁片段或活動的 ID
  4. 按一下「Text」(文字) 分頁標籤,切換至 XML 檢視畫面。現已在來源到達網頁中新增操作元素。操作具有 ID 和到達網頁屬性,其中包含下一個到達網頁的 ID,如以下範例所示:

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

在導覽圖表中,操作是以 <action> 元素表示。操作至少應包含本身的 ID 和到達網頁 (使用者應前往這個頁面) ID。

使用 NavController,也就是在 NavHost 中管理應用程式瀏覽的物件,瀏覽到目的地。每個 NavHost 都有其對應的 NavController。您可以使用下列任一方法擷取 NavController

Kotlin:

Java:

當使用 FragmentContainerView 建立 NavHostFragment 時,或者透過 FragmentTransaction 手動將 NavHostFragment 新增至活動時,嘗試透過 Navigation.findNavController(Activity, @IdRes int) 擷取「活動」onCreate() 中的 NavController 將會失敗。請改為直接從 NavHostFragment 擷取 NavController

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

使用 Safe Args 確保類型安全

我們建議您使用 Safe Args Gradle 外掛程式在到達網頁之間瀏覽。此外掛程式會產生簡單的物件和建構工具類別,可以啟用類型安全瀏覽功能及在不同到達網頁之間傳遞引數。

如要在專案中新增 Safe Args,請在頂層 build.gradle 檔案中納入下列 classpath

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

您也必須從兩個可用的外掛程式之中選擇一項套用。

如要產生適合 Java 或混用 Java 及 Kotlin 模組的 Java 語言程式碼,請將以下這一行新增至應用程式或模組build.gradle 檔案:

Groovy

plugins {
  id 'androidx.navigation.safeargs'
}

Kotlin

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

或者,如要產生適合 Kotlin 模組的 Kotlin 程式碼,請加入:

Groovy

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

Kotlin

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

根據遷移至 AndroidX 一文,gradle.properties 檔案中必須含有 android.useAndroidX=true

啟用安全機制之後,外掛程式會產生程式碼,其中包含您定義的每個操作的類別和方法。對各個操作項目來說,Safe Args 也會為每個「原始到達網頁」產生類別,原始到達網頁也就是該操作的來源到達網頁。產生的類別名稱是由原始到達網頁類別名稱和「Directions」(路線) 字詞組合而成。舉例來說,如果到達網頁名稱為 SpecifyAmountFragment,產生的類別就會命名為 SpecifyAmountFragmentDirections。原始到達網頁中定義了各項操作,而產生的類別包含每種操作的靜態方法。這個方法會將任何已定義的操作參數視為引數,並傳回可傳遞至 navigate()NavDirections 物件。

舉例來說,假設有一個導覽圖表包含單一操作,可將原始到達網頁 (SpecifyAmountFragment) 連結至接收到達網頁 (ConfirmationFragment),就是這裡所說的情形。

安全機制產生的 SpecifyAmountFragmentDirections 單一類別方法 actionSpecifyAmountFragmentToConfirmationFragment() 會傳回 NavDirections 物件。接著,系統會將返回的 NavDirections 物件直接傳送到 navigate(),如以下範例所示:

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

如要進一步瞭解如何透過 Safe Args 在到達網頁之間傳送資料,請參閱「使用 Safe Args 傳送類型安全的資料」。

更多資訊

如果您在使用導覽功能時遇到任何問題,請透過下列其中一種管道提交意見回饋:

如要瞭解如何在錯誤報告中提供最實用的資訊,請參閱下列連結: