Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

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

Navigation コンポーネントは、ナビゲーション グラフを使用してアプリのナビゲーションを管理します。ナビゲーション グラフは、アプリ内のすべてのデスティネーションとともに、ユーザーがデスティネーション間を移動する際にたどる可能性がある論理的な道筋(アクション)を格納するリソース ファイルです。Android Studio の Navigation Editor を使用して、アプリのナビゲーション グラフを管理できます。

このトピックでは、アプリのナビゲーション グラフを設計する際のベスト プラクティスと推奨事項について説明します。

トップレベル ナビゲーション グラフ

アプリのトップレベル ナビゲーション グラフは、ユーザーがアプリを起動したときに最初に表示される開始デスティネーションから始まり、ユーザーがアプリ内を移動する際に表示されるすべてのデスティネーションを含む必要があります。

図 1: トップレベル ナビゲーション グラフ

ネストグラフ

一般的に、アプリ内のログインフロー、ウィザード、その他のサブフローは、ネストされたナビゲーション グラフとして表現するのが最も適切です。このように自己完結型のサブナビゲーション フローをネストすることにより、アプリの UI のメインフローの把握と管理が容易になります。また、ネストグラフは再利用可能です。さらに、一定レベルのカプセル化も実現できます。ネストグラフの外部にあるデスティネーションは、ネストグラフの内部にあるデスティネーションに直接アクセスすることができません。代わりに、navigate() を使用して、ネストグラフ自体にアクセスする必要があります。ネストグラフの内部ロジックは、グラフの残りの部分に影響を与えることなく変更できます。

図 1 のトップレベル ナビゲーション グラフの例で、ユーザーがアプリを初めて起動したときに限り、title_screen 画面と register 画面を表示したいとします。さらに、ユーザー情報を保存して、次回以降のアプリの起動時には、直接 match 画面にユーザーを誘導するとします。ベスト プラクティスとしては、match 画面をトップレベル ナビゲーション グラフの開始デスティネーションに設定し、title_screen 画面と register 画面をネストグラフに移動するのが適切です。図 2 をご覧ください。

図 2: ネストグラフが追加されたトップレベル ナビゲーション グラフ

match 画面が起動したら、登録済みユーザーがいるかどうかをチェックします。ユーザーが登録されていない場合は、ユーザーを register 画面に誘導します。条件付きナビゲーション シナリオの詳細については、条件付きナビゲーションをご覧ください。

グラフ構造をモジュール化するもう 1 つの方法は、親ナビゲーション グラフ内の <include> 要素を介して、別のグラフを子グラフとして組み込むことです。この方法では、組み込まれる側のグラフを独立したモジュールまたはプロジェクト内で定義できるため、最大限の再利用可能性を実現できます。

ナビゲーション グラフを格納するライブラリ モジュールにアプリが依存している場合は、<include> 要素を使用して、それらのナビゲーション グラフを参照できます。

上記のトリビアゲームの例で、アプリの中核のゲーム部分を独立したライブラリ モジュールに分離するとします。これにより、in_game 画面、results_winner 画面、game_over 画面をさまざまなアプリに組み込むことが可能になります。以下の例をご覧ください。

<!-- App Module Navigation Graph -->
<navigation 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"
           app:startDestination="@id/match">

   <fragment android:id="@+id/match"
           android:name="com.example.android.navigationsample.Match"
           android:label="fragment_match">

       <!-- Launch into In Game Modules Navigation Graph -->
       <action android:id="@+id/action_match_to_in_game_nav_graph"
           app:destination="@id/in_game_nav_graph" />
   </fragment>

   <include app:graph="@navigation/in_game_navigation" />

</navigation>
<!-- Game Module Navigation Graph -->
<?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/in_game_nav_graph"
   app:startDestination="@id/in_game">

   <fragment
       android:id="@+id/in_game"
       android:name="com.example.android.gamemodule.InGame"
       android:label="Game">
       <action
           android:id="@+id/action_in_game_to_resultsWinner"
           app:destination="@id/results_winner"  />
       <action
           android:id="@+id/action_in_game_to_gameOver"
           app:destination="@id/game_over"  />
   </fragment>

   <fragment
       android:id="@+id/results_winner"
       android:name="com.example.android.gamemodule.ResultsWinner" >

       <!-- Action back to destination which launched into this in_game_nav_graph-->
       <action android:id="@+id/action_pop_out_of_game"
                           app:popUpTo="@id/in_game_nav_graph" />

   </fragment>

   <fragment
       android:id="@+id/game_over"
       android:name="com.example.android.gamemodule.GameOver"
       android:label="fragment_game_over"
       tools:layout="@layout/fragment_game_over" >

      <!-- Action back to destination which launched into this in_game_nav_graph-->
       <action android:id="@+id/action_pop_out_of_game"
                           app:popUpTo="@id/in_game_nav_graph" />

 </fragment>

</navigation>

トップレベル グラフをメインアプリ モジュール内に格納し、参照が必要なナビゲーションを格納するモジュールに対して Gradle 参照を設定します。

グローバル アクション

アプリのデスティネーションに到達できるパスが複数ある場合、そのデスティネーションに移動するためのグローバル アクションを定義する必要があります。グローバル アクションを利用すると、どこからでも対象のデスティネーションに移動できるようになります。

グローバル アクションを上記のライブラリ モジュール サンプルに適用してみましょう。このサンプルでは、results_winner デスティネーションと game_over デスティネーションの両方に対して同じアクションが定義されています。この共通アクションを単一のグローバル アクションとして抽出し、両方のデスティネーションから参照するようにします。以下の例をご覧ください。

<?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/in_game_nav_graph"
   app:startDestination="@id/in_game">

   <!-- Action back to destination which launched into this in_game_nav_graph-->
   <action android:id="@+id/action_pop_out_of_game"
                       app:popUpTo="@id/in_game_nav_graph"
                       app:popUpToInclusive="true"  />

   <fragment
       android:id="@+id/in_game"
       android:name="com.example.android.gamemodule.InGame"
       android:label="Game">
       <action
           android:id="@+id/action_in_game_to_resultsWinner"
           app:destination="@id/results_winner"  />
       <action
           android:id="@+id/action_in_game_to_gameOver"
           app:destination="@id/game_over"  />
   </fragment>

   <fragment
       android:id="@+id/results_winner"
       android:name="com.example.android.gamemodule.ResultsWinner" />

   <fragment
       android:id="@+id/game_over"
       android:name="com.example.android.gamemodule.GameOver"
       android:label="fragment_game_over"
       tools:layout="@layout/fragment_game_over" />

</navigation>

フラグメント内でグローバル アクションを使用する方法の詳細と例については、ナビゲーション ドキュメントのグローバル アクションをご覧ください。