ナビゲーション グラフを設計する

Navigation コンポーネントでは、ナビゲーション グラフを使用してアプリのナビゲーションを管理します。ナビゲーション グラフとは、アプリ内の各デスティネーションと、それらの間の接続を含むデータ構造です。

デスティネーションのタイプ

デスティネーションの一般的なタイプとしては、ホストされているデスティネーション、アクティビティのデスティネーション、ダイアログのデスティネーションの 3 つがあります。次の表に、これら 3 つのデスティネーション タイプとその用途をまとめます。

タイプ

説明

使用場面

ホストされているデスティネーション

ナビゲーション ホスト全体を埋めるデスティネーションです。ホストされたデスティネーションのサイズはナビゲーション ホストのサイズと同じとなり、それ以前のデスティネーションは表示されなくなります。

メイン画面や詳細画面。

ダイアログのデスティネーション

オーバーレイ UI コンポーネントを表すデスティネーションです。この UI は、ナビゲーション ホストの場所やサイズには関連付けられません。それ以前のデスティネーションは、このデスティネーションの下に表示されます。

アラート、選択肢、フォーム。

アクティビティのデスティネーション

アプリ内の固有の画面または機能を表すデスティネーションです。

ナビゲーション グラフの終了ポイントとして機能し、Navigation コンポーネントとは別に管理されている新しい Android アクティビティを開始します。

最新の Android 開発では、アプリを 1 つのアクティビティで構成します。アクティビティのデスティネーションは、サードパーティ アクティビティとやり取りする場合や、移行プロセスの一部として使用するのが最適です。

このドキュメントでは、最も一般的で基本的なデスティネーションである「ホストされているデスティネーション」の例を示します。それ以外のデスティネーションについては、以下のガイドをご覧ください。

フレームワーク

どの場合にも同じ一般的なワークフローが適用されますが、ナビゲーション ホストとグラフの作成方法は使用する UI フレームワークによって異なります。

  • Compose で作成する: NavHost コンポーザブルを使用します。次のコマンドを使用して、NavGraph を追加します。 Kotlin DSL。グラフは次の 2 つの方法で作成できます。
    • NavHost の一部として作成する: NavHost を追加する際に、その一部としてナビゲーション グラフを直接作成します。
    • プログラマティックに作成する: NavController.createGraph() メソッドを使用して NavGraph を作成し、直接 NavHost に渡します。
  • フラグメント: View UI フレームワークでフラグメントを使用する場合は、 ホストとして NavHostFragment。ナビゲーションを作成するにはいくつかの方法があります graph: <ph type="x-smartling-placeholder">
      </ph>
    • プログラマティックに作成する: Kotlin DSL を使用して NavGraph を作成する。 NavHostFragment で直接適用します。
      • 両方の Kotlin DSL で使用される createGraph() 関数 フラグメントと Compose は同じです。
    • XML で作成する: ナビゲーション ホストとグラフを XML で直接記述します。
    • Android Studio エディタ: Android Studio の GUI エディタを使用して、グラフを XML リソース ファイルとして作成、調整します。

Compose

Compose では、シリアル化可能なオブジェクトまたはクラスを使用してルートを定義します。ルート デスティネーションへの到達方法が記述されており、 指定することもできます。ルートを定義したら、NavHost を使用します。 使用してナビゲーション グラフを作成します。次の例を考えてみましょう。

@Serializable
object Profile
@Serializable
object FriendsList

val navController = rememberNavController()

NavHost(navController = navController, startDestination = Profile) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
    // Add more destinations similarly.
}
  1. シリアル化可能なオブジェクトは、Profile と 2 つのルートのそれぞれを表します。 FriendsList
  2. NavHost コンポーザブルの呼び出しでは、NavController とルートが渡されます。 指定します。
  3. NavHost に渡されたラムダにより、最終的に NavController.createGraph() が呼び出され、NavGraph が返されます。
  4. 各ルートは、type 引数として NavGraphBuilder.composable<T>(): デスティネーションを 結果として NavGraph になります。
  5. composable に渡されるラムダが、それに対して NavHost に表示されます。 あります。
で確認できます。

ラムダを理解する

NavGraph を作成するラムダについては、前のスニペットで作成したのと同じグラフを作成するためのものと考えると理解しやすいでしょう。NavController.createGraph() を使用して個別に NavGraph を作成し、直接 NavHost に渡すことができます。

val navGraph by remember(navController) {
  navController.createGraph(startDestination = Profile)) {
    composable<Profile> { ProfileScreen( /* ... */ ) }
    composable<FriendsList> { FriendsListScreen( /* ... */ ) }
  }
}
NavHost(navController, navGraph)

引数を渡す

デスティネーションにデータを渡す必要がある場合は、 パラメータがあります。たとえば、Profile ルートは name を持つデータクラスです。 パラメータを指定します。

@Serializable
data class Profile(val name: String)

そのデスティネーションに引数を渡す必要があるたびに、インスタンスを作成する 引数をクラス コンストラクタに渡します。

ルート インスタンスを取得する

ルート インスタンスは、NavBackStackEntry.toRoute() または SavedStateHandle.toRoute()。「kubectl」コマンドを使用して composable() の場合、NavBackStackEntry はパラメータとして利用できます。

@Serializable
data class Profile(val name: String)

val navController = rememberNavController()

NavHost(navController = navController, startDestination = Profile(name="John Smith")) {
    composable<Profile> { backStackEntry ->
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(name = profile.name) }
}

このスニペットでは、次の点に注意してください。

  • Profile ルートはナビゲーションの開始デスティネーションを指定する ("John Smith"name の引数として指定しています)。
  • デスティネーション自体は composable<Profile>{} ブロックです。
  • ProfileScreen コンポーザブルは、独自の値 profile.name を受け取ります。 name 引数。
  • そのため、値 "John Smith"ProfileScreen に渡されます。

最も簡単な例

以下に、NavControllerNavHost が連動する完全な例を示します。

@Serializable
data class Profile(val name: String)

@Serializable
object FriendsList

// Define the ProfileScreen composable.
@Composable
fun ProfileScreen(
    profile: Profile
    onNavigateToFriendsList: () -> Unit,
  ) {
  Text("Profile for ${profile.name}")
  Button(onClick = { onNavigateToFriendsList() }) {
    Text("Go to Friends List")
  }
}

// Define the FriendsListScreen composable.
@Composable
fun FriendsListScreen(onNavigateToProfile: () -> Unit) {
  Text("Friends List")
  Button(onClick = { onNavigateToProfile() }) {
    Text("Go to Profile")
  }
}

// Define the MyApp composable, including the `NavController` and `NavHost`.
@Composable
fun MyApp() {
  val navController = rememberNavController()
  NavHost(navController, startDestination = Profile(name = "John Smith")) {
    composable<Profile> { backStackEntry ->
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(
            profile = profile,
            onNavigateToFriendsList = {
                navController.navigate(route = FriendsList)
            }
        )
    }
    composable<FriendsList> {
      FriendsListScreen(
        onNavigateToProfile = {
          navController.navigate(
            route = Profile(name = "Aisha Devi")
          )
        }
      )
    }
  }
}

このスニペットでは、NavController をコンポーザブルに渡す代わりに、イベントを NavHost に公開しています。この場合、コンポーザブルには、NavHostNavController.navigate() を呼び出すラムダを渡すための () -> Unit 型のパラメータが必要となります。

フラグメント

前のセクションで説明したように、フラグメントを使用すると、Kotlin DSL、XML、または Android Studio エディタを使用して、プログラマティックにナビゲーション グラフを作成できます。

以降のセクションでは、これらの方法について詳しく説明します。

プログラマティック

Kotlin DSL を使用すると、フラグメントによるナビゲーション グラフをプログラマティックに作成できます。XML リソース ファイルを使用する方法に比べ、多くの点でより簡潔で先進的な方法です。

次の例で、2 画面のナビゲーション グラフを実装する場合を考えてみましょう。

まず、NavHostFragment を作成する必要があります。ただし、このファイルを含め app:navGraph 要素:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

次に、NavHostFragmentidNavController.findNavController に渡します。これにより、NavController が NavHostFragment

その後、NavController.createGraph() を呼び出すと、グラフが NavController、ひいては NavHostFragment に対する引数:

@Serializable
data class Profile(val name: String)

@Serializable
object FriendsList

// Retrieve the NavController.
val navController = findNavController(R.id.nav_host_fragment)

// Add the graph to the NavController with `createGraph()`.
navController.graph = navController.createGraph(
    startDestination = Profile(name = "John Smith")
) {
    // Associate each destination with one of the route constants.
    fragment<ProfileFragment, Profile> {
        label = "Profile"
    }

    fragment<FriendsListFragment, FriendsList>() {
        label = "Friends List"
    }

    // Add other fragment destinations similarly.
}

この方法での DSL の使用は、前の Compose のセクションで説明したワークフローと非常によく似ています。たとえば、どちらの場合も NavController.createGraph() 関数で NavGraph を生成します。同様に、NavGraphBuilder.composable() はコンポーザブルのデスティネーションをグラフに追加しますが、この場合は NavGraphBuilder.fragment() がフラグメント デスティネーションを追加します。

Kotlin DSL の使用方法については、NavGraphBuilder DSL でグラフを作成するをご覧ください。

XML

XML は自分で直接記述できます。次の例は、前のセクションの 2 画面の例と同等のものです。

まず、NavHostFragment を作成します。これは、実際のナビゲーション グラフを含むナビゲーション ホストとして機能します。

次に、NavHostFragment の最小限の実装を示します。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:navGraph="@navigation/nav_graph" />

</FrameLayout>

NavHostFragment には、属性 app:navGraph が含まれています。この属性を使用する ナビゲーション グラフをナビゲーション ホストに接続します。次に、グラフの実装方法の例を示します。

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/profile">

    <fragment
        android:id="@+id/profile"
        android:name="com.example.ProfileFragment"
        android:label="Profile">

        <!-- Action to navigate from Profile to Friends List. -->
        <action
            android:id="@+id/action_profile_to_friendslist"
            app:destination="@id/friendslist" />
    </fragment>

    <fragment
        android:id="@+id/friendslist"
        android:name="com.example.FriendsListFragment"
        android:label="Friends List" />

    <!-- Add other fragment destinations similarly. -->
</navigation>

アクションを使用して、個別のデスティネーション間の接続を定義します。この例では、friendslist に移動するアクションが profile フラグメントに含まれています。詳細については、ナビゲーション アクションとフラグメントを使用するをご覧ください。

編集者

アプリのナビゲーション グラフは、Android Studio の Navigation Editor を使用して管理できます。前のセクションでも使用したこのエディタは、NavigationFragment の XML の作成と編集に使用できる GUI です。

詳しくは、Navigation Editor をご覧ください。

ネストされたグラフ

ネストされたグラフを使用することもできます。その場合は、グラフをナビゲーション デスティネーションとして使用します。詳しくは、ネストされたグラフをご覧ください。

関連情報

ナビゲーションの基本的な概念については、以下のガイドをご覧ください。