〈kotlin〉Navigation①

Android studioでkotlinを使ってAndroidアプリ作成の勉強中。

画面遷移の設定に使用するNavigationコンポーネントの使い方をまとめてみる。

Navigationコンポーネントとは

アプリ内のさまざまなコンテンツ間を移動する操作を実装する。
以下の3つの要素で構成されている。

ナビゲーション グラフ すべてのナビゲーション関連情報を 1 つの場所で集中的に保管する XML リソース
NavHost ナビゲーション グラフからの宛先を表示する空のコンテナ
NavController NavHost 内のアプリ ナビゲーションを管理するオブジェクト

アプリ内を移動するとき、ナビゲーション グラフ内の特定のパスをたどって移動するか、
それとも特定の宛先に直接移動するかを NavController に伝える。
NavController はそれに応じて NavHost に適切な宛先を示す。

実装

build.gradle
implementation "androidx.navigation:navigation-fragment-ktx:2.4.1"
implementation "androidx.navigation:navigation-ui-ktx:2.4.1"
各Fragmentの準備

遷移したい画面ごとにFragmentとレイアウトファイルを作成する。

ナビゲーショングラフの作成
  1. resディレクトリで右クリックし、「New Resource File」を開く。
  2. FileNameを「nav_graph」、Resource typeを「Navigation」としてOKを押す。
  3. 「New Destination」から遷移を設定したいFragmentを追加する。(最初に追加したFragmentがトップのFragmentに設定される🏠)
  4. 「Add Action」から移動方向を追加する。

Fragmentを追加するとコードにid,name,label,layoutは自動で追加される。
actionで移動方向を設定すると、出発地のFragmentにactionタグが作成され、
actionに対するidと移動先のFragment名が設定される。

<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"
    android:id="@+id/nav_graph"
    app:startDestination="@id/firstFragment">

    <fragment
        android:id="@+id/firstFragment"
        android:name="com.example.sampleApp.firstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first" >
        <action
            android:id="@+id/action_firstFragment_to_secondFragment"
            app:destination="@id/secondFragment" />
    </fragment>
    <fragment
        android:id="@+id/secondFragment"
        ...
        <action
            android:id="@+id/action_secondFragment_to_thirdFragment"
            app:destination="@id/thirdFragment"
    </fragment>
    <fragment
        android:id="@+id/thirdFragment"
        ...>
        <action
            android:id="@+id/action_thirdFragment_to_firstFragment"
            app:destination="@id/firstFragment"
            
            //☆
            //以下の設定については後述
            app:popUpTo="@id/firstFragment"
            app:popUpToInclusive="true"/>
    </fragment>
</navigation>

上記のnav_graphはfirst→second→thirdと遷移したあと、
third→firstに戻るように作成した。
このとき画面はfirst,second,thirdの順にスタックに積まれていて、
コード内の☆の部分を書かずにfisrtへのactionを追加すると
スタックはfirst,second,third,firstと積まれることになる。
(2回目のfirstの画面で戻るボタンを押すとthirdに戻る。)

☆の設定は、
popUpTo:スタックの一番上に残すFragmentを指定。それ以外のバックスタックは破棄。
popUpToInclusive:popUpToで指定したFragmentもバックスタックから破棄するかどうか。

この設定を追加すると、
third→firstの遷移時にバックスタックが破棄されて、
スタックにはfirstだけが残った状態になる。
(2回目のfirstの画面で戻るボタンを押してもthirdに戻らない。)

popUpToInclusiveをFalseにすると、
popUpToで指定したFragment(今回はfirst)はバックスタックから削除されなくなるため、
first→second→third→firstと遷移したときのスタックには
firstが2つ積まれた状態になる(多分)。

NavHostの追加

activity_main.xmlにNavHostFragmentを追加する。

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

defaultNavHostをtrueにすると、
システムの戻るボタンにも画面遷移が対応するようになる。
navGraphに作成したナビゲーショングラフ名を指定する。

NavController

firstFragmentにボタンクリックでsecondFragmentへ移動を実装する。

binding.button.setOnClickListener{
    findNavController().navigate(R.id.action_firstFragment_to_secondFragment)
    //idはnav_graph内で設定したaction id
}

action idを直接指定して実装もできるが、
Safe Argsを使用して実装することが推奨されている。
Safe Argsを使用した実装はまた次回。

参考https://developer.android.com/guide/navigation/navigation-getting-started?hl=ja