カテゴリー
Kotlin言語

ゼロから始めるAndroidアプリ(Kotlin編)Unit3 – 2:フラグメント5(ナビゲーションコンポーネントの使い方)

Android Developers > スタートガイド > Kotlin と Android をゼロから学ぶ > Unit3 – ナビゲーションUnit3-2 の内容をまとめたものです(翻訳ではありません)


ナビゲーション・コンポーネント(Jetpack Navigation Component)とは

フラグメントの移動(ナビゲーション)にはナビゲーション・コンポーネントを使うの

インテントは使わないんですね

  • ナビゲーションコンポーネント(Navigation component)は Android Jetpack で提供されています
  • 簡単なものから複雑なものまで、アプリに実装するあらゆるナビゲーション(画面遷移)を作成できます
  • このチュートリアルで作成中のフラグメントを使った単語アプリにナビゲーションを追加しながら説明します

ナビゲーションコンポーネントの3つの部分

ナビゲーションコンポーネントは3つの部分からできています

NavGraph(ナビグラフ, ナビゲーショングラフ, Navigation Graph)

NavGraph にはビジュアルエディタがあるのでマウスで簡単に作れちゃいます

NavGraph の中でフラグメントはデスティネーション(destination)って呼ぶの

  • NavGraph は XML ファイルになっています。アプリのナビゲーションを視覚的に表現したものを提供します
  • ファイルは個々のアクティビティやフラグメントに対応したデスティネーション(destination)と、それらをつなぐアクション(action)から成ります
  • アクションは、あるデスティネーションから別のデスティネーションを起動するためのコードで使われます
  • NavGraph の作成には、レイアウトファイルの作成と同じように Android Studio のビジュアルエディターが利用できます。デスティネーションとアクションをマウス操作で簡単に追加できます

NavHost(ナビホスト)

フラグメントは NavHost の中に表示するんですよね

  • NavHost は NavGraph のデスティネーション(フラグメントやアクティビティ)を特定のアクティビティ内に表示するのに使われます
  • フラグメント間の移動に合わせて、NavHost に表示されるデスティネーションが更新されます
  • MainActivity に NavHost を設定するときは、NavHostFragment という実装が用意されてるのでこれを使います

NavController(ナビコントローラ)

NavHost にフラグメントを表示するのは NavController のお仕事なの

  • NavHost に表示するデスティネーションは、NavController オブジェクトを使って操作します
  • インテントでは、新しい画面を表示するのに startActivity を使いました
  • ナビゲーションコンポーネントでは、NavController のnavigate() メソッドを使って NavHost に表示するフラグメントを入れ替えます
  • NavController は「UPボタン(前に表示されていたフラグメントに戻るためのボタン)」のようなシステムに共通の処理にも対応しています

ナビゲーションコンポーネントを利用するための準備

ナビゲーションコンポーネントを使うには Android Studio への設定が必要なの

Gradle の設定ですね

ナビゲーションコンポーネントを利用するには、Gradle への設定が必要です

build.gradle(Project)の設定

  • プロジェクトレベルの build.gradle ファイルを開きます
  • buildscript の ext の中、material_version の下に nav_version を 2.3.1 で設定します
  • 以下のようになります
buildscript {
    ext {
        appcompat_version = "1.2.0"
        constraintlayout_version = "2.0.2"
        core_ktx_version = "1.3.2"
        kotlin_version = "1.3.72"
        material_version = "1.2.1"
        nav_version = "2.3.1"
    }

    ...

build.gradle(Module)の設定

  • モジュール(アプリ)レベルの build.gradleファイルを開きます
  • dependencies に以下を追加します
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
  • Gradle のファイルを編集すると、上の方にプロジェクトを同期(Sync)するかどうか尋ねる黄色いバナーが出ます
  • “Sync Now” をクリックすると設定変更を反映するように Gradle がプロジェクトの依存性を更新します

Safe Args プラグインを設定する

Safe Args プラグインも有効にしますね

これも Gradle の設定ですね

  • アクティビティ版の単語アプリでは、アクティビティからアクティビティへ、明示的インテントを使って移動しました
  • アクティビティへデータ(選択された文字)を渡すのには putExtra() メソッドを使いました
  • フラグメント間でデータをやりとりするときは Safe Args というプラグインを使うようにします
  • Safe Args は Gradle のプラグインで、フラグメント間でデータをやりとりするときに型安全になるようにサポートします
  • 次のようにして Safe Args をプロジェクトに設定します

build.gradle(Project)の設定

  • プロジェクトレベルの build.gradle ファイルを開きます
  • buildscript の中の dependencies に、次の classpath を追加します
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"

build.gradle(Module)の設定

  • モジュール(アプリ)レベルの build.gradleファイルを開きます
  • 先頭のほうにある plugins の中に  androidx.navigation.safeargs.kotlin を追加します
plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-kapt'
    id 'androidx.navigation.safeargs.kotlin'
}

NavGraph(ナビグラフ)を使う準備

NavGraph はビジュアルツールで簡単に作成できるんです

  • ナビゲーションコンポーネントはナビゲーション、特にフラグメント間のナビゲーションを実装するためのツールを集めたものです
  • フラグメント間のナビゲーションを作成するのに NavGraph(ナビグラフ)のビジュアルエディタを使ってみます

NavGraph とは

  • NavGraph(ナビグラフ, ナビゲーショングラフ)はアプリのナビゲーションを視覚的に表したものです
  • アプリにあるナビゲーションの対象になる画面(フラグメント)を「デスティネーション(destination)」と呼びます
  • NavGraph は XML ファイルで表されています。デスティネーション同士が、お互いにどんな風に関連しているかを示しています
  • NavGraph クラスのインスタンスが新たに作られ、画面には FragmentContainerView を使って表示されます
  • ビジュアルエディタを使ってXMLファイルにデスティネーションを設定していくだけで、フラグメント間を移動するためのコードが自動的に生成されます

NavHost の設定

NavGraph を使う前に NavHost の設定をしちゃいますね

NavHost の設定は activity_main.xml の中ですよね

うん、FragmentContainerView っていうのを設定するの

  • NavHost を設定するには activity_main.xml に FragmentContainerView を設定します
  • アプリのUI画面はフラグメント(fragment_letter_list.xml , fragment_word_list.xml)で作成します。activity_main.xml は NavHost として、フラグメントを表示する場所(FragmentContainerView)を提供します
  • NavHost を設定すると、アプリのすべてのナビゲーションが FragmentContainerView の中で行われるようになります
  • activity_main.xml の RecyclerView の設定はすでにフラグメントへコピーしてあるので削除します。代わりに FragmentCotainerView を次のように設定します
<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:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />
  • id名は nav_host_fragment とします
  • name 属性で NavHostFragment を設定しますFragmentContainerView が NavHostFragment を使ってフラグメントをナビゲートできるようになります
  • 幅と高さは、フレームレイアウト全体を満たすように match_parent とします
  • app:navHost 属性を追加して “true” に設定します。これによって FragmentContainerView と NavGraph で作成したナビゲーションの階層が互いに関連付けられます。システムの UP(戻る)ボタンが押されたら、コンテナが前に表示されていたフラグメントを表示するような動作が可能になります
  • app:navGraph 属性を追加して “@navigation/nav_graph” と設定します。これは NavGraph の XML ファイル名の指定です
  • まだ NavGraph を作成していない(nav_graph.xml が存在しない)ので Android Studio がエラーを表示します。このあと作成するので今はそのままにしておきます
  • 最後に、app ネームスペースをもった属性を追加しているので、FrameLayout に xmlns:app 属性を設定します
  • まとめると activity_main.xml は次のようになります
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <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:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />
</FrameLayout>

NavGraph を作成する

いよいよ NavGraph を作成しちゃいます

  • NavGraph のファイル(Project ペインで res フォルダを選択して File > New > Android Resource File)を作成します。ダイアログのフィールドは次のようにします
    • File Name:nav_graph.xml(app:navGraph 属性で設定した名前と同じにします)
    • Resource Type:Navigation
    • Directory Name:navigation(自動的に変更されます。navigation という新しいリソースフォルダーが生成されます)
  • nav_graph.xml が生成され、NavGraph を作成するためのビジュアルエディターで表示されます
  • デスティネーション(destination)を追加するには画面左上にある new ボタンをクリックします。表示されるフラグメントを選択していくだけでコードが自動的に生成されます
    • デスティネーションとして fragment_letter_list と fragment_word_list を追加します
    • デスティネーションの名前は、それぞれ letterListFragment と wordListFragment になります
  • デスティネーションの選択は、左にある Component Tree を使うことでも可能です

ナビゲーションアクションを生成する

マウスでドラッグ&ドロップするだけなの

  • デスティネーション間のアクション(ナビゲーションアクション)は、マウスでドラッグするだけで作成できます
  • letterListFragment から wordListFragment へのアクションを作成します。手順は次の通りです
    1. マウスのポインタを letterListFragment の上に移動させます
    2. 右の方に現れる円をつかんで wordListFragment の上までドラッグしてドロップします
    3. アクションをあらわす矢印が表示されればアクションの生成完了です
  • 矢印をクリックしてみます。右の attributes ペインに action_letterListFragment_to_wordListFragment という名前が表示されることを確認します。Kotlinコードの中でこのアクションを参照するときはこの名前を使います

アクションの名前、ちょっと長いかも…

フラグメントで引数を使う

フラグメントではエクストラの代わりに arguments を使ってくださいね

  • アクティビティ版の単語アプリでは、画面で選択された文字を次の画面に渡すのにインテントのエクストラ(extra)を利用しました
  • ナビゲーションコンポーネントでは次のようにしてデスティネーション間でデータを渡します。Safe Args プラグインを使うことで型安全もサポートされます
    1. wordListFragment デスティネーションを選択します
    2. 右の Attributes ペインの Arguments のところで + ボタンをクリックして新しい属性を追加します
    3. ダイアログが開くので Name を letter、Type を String にして Add ボタンをクリックします
  • Safe Args プラグインを利用することで、ナビゲーションアクションでコードを実行するとき、引数 letter は必ず String 型として扱われるようになります

スタートデスティネーションの設定

アプリを起動したときに一番最初に表示される画面のことですね

  • activity_main.xml に設定した FragmentContainerView が最初に表示するフラグメントをスタートデスティネーション(start destination)として設定します
  • スタートデスティネーションの設定は、NavGraph でデスティネーション(今回は letterListFragment)を選択して、Assign start destination ボタン(家のアイコン)をクリックするだけで完了します
  • NavGraph への設定は以上です

アプリをビルドして実行する

とりあえず実行しちゃいますね

  • アプリをビルドして実行してみます
  • エラーなくアプリが起動できることを確認します。ナビゲーションアクションを記述していないので画面の移動はできません
  • NavGraph に基づいてコードが生成されています。アプリのナビゲーションは、この生成されたコード(ナビゲーションアクション)を使って行います