[Android]Navigation でシンプルな画面遷移を最速で実装する


はじめに

JetpackNavigation はすごく便利ですよね。
最近ちょくちょく利用するのですが実装の仕方を忘れてしまいます。

なので忘れても Navigation を最速で実装できるようにするため、
1つの Activity で 複数のFragment を切り替えるアプリの作成方法をまとめます。

準備

Navigation を利用したアプリケーションを作成するための下準備をします。
次の手順で必要なライブラリやクラス、レイアウトを生成していきます。

Navigation をセットアップする

次の内容を dependencies に記述するとNavigationをインストールできます。
JavaKotlin でインストール方法が違うので注意が必要です。

build.gradle(app)
dependencies {
    def nav_version = "2.1.0"
    implementation "androidx.navigation:navigation-fragment:$nav_version"
    implementation "androidx.navigation:navigation-ui:$nav_version"

    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}

Fragment を作成する

Navigation を使った遷移で利用する Fragment を作成していきます。
次の手順で OneFragment, TwoFragment, ThreeFragment の 3つを作成します。

  1. Package Name を右クリックし、New → Fragment → Fragment(Blank) を選択する
  2. Fragment Name任意の名称 を入力し OK を押す
  3. Fragment にいらない記述が書かれているので消す
  4. LayoutFragment に遷移させるための Button を追加する
Fragment.kt
class OneFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_one, container, false)
    }
}

layout.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".OneFragment">

    <Button
            android:id="@+id/nav_button"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="@string/hello_blank_fragment" />

</FrameLayout>

実装

Navigation を利用するには次の3つを実装する必要があります。
それらの 3 つの実装を 1 つずつ進めていきます。

No 名称 役割
1 Navigation Graphの作成 宛先などナビゲーションの情報を管理する XML ファイルを作成する
2 Nav Hostの作成 Nav HostNavigation Graph の宛先を表示するための空のコンテナのこと
Fragment を表示するのでNavHostの実装であるNavHostFragmentを作成する
3 Nav Controllerで画面を遷移させる Nav Host に表示するコンテンツをNavigation Graphを元に
切り替える処理をするNav Controllerを取得し、画面を遷移させる。

Navigation Graph の作成

宛先などのナビゲーション情報を管理するNavigation Graphを作成します。

リソースファイルの作成

Navigation Graphはどこからどこへ遷移するかをリソースファイルに記述したものです。
なのでまずはNavigation Graphのリソースファイルを作成します。

  1. res を右クリックし New → Android Resource File を選択する
  2. File namenav_graph , Resource TypeNavigation を入力する

遷移先の組み立て

作成した nav_graph を開くとNavigation Editorが表示されます。
この Navigation Editor を利用して、どこからどこへ遷移するかを決めていきます。

次の操作でどこからどこへ遷移するか設定できます。今回はOneFragment から TwoFragment
TwoFragmentからThreeFragmentThreeFragmentからOneFragmentに遷移させます。

  1. 📱をクリックして OneFragment, TwoFragment, ThreeFragment を追加する
  2. OneFragmentからTwoFragment, TwoFramgentからThreeFragment
    ThreeFragmentからOneFragment に線を引く

Nav Host の作成

Navigation Graph で定義したコンテンツを表示するための空のコンテナを作成します。
Activityのレイアウトにfragmentを追加した後、
次のAttributeを追加することでNav Host Fragmentを定義できます。

Attribute Value 説明
android:name NavHostFragment どのNavHostの実装を利用するか指定できる。
今回はFragmentを表示するためのNavHostFragmentを指定する。
app:navGraph @navigation/nav_graph どのNavigation Graphを利用するか設定できる。
今回はさっき作成したNavigation Graphをここで指定する。
app:defaultNavHost true NavHostFragmentBACKボタンを無効化できる。
今回はBACKボタンでホームに戻りたくないので有効化しておく
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<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">

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

Nav Controller で画面を遷移させる

Nav Controllerを取得し、Buttonをクリックした時にFragmentを遷移させる処理を実装する。

Nav Controller を取得する

Nav Controller を取得する方法は 3つあります。
次のように FragmentView , Activity から取得する方法があります。

Fragment.findNavController()
View.findNavController()
Activity.findNavController(viewId: Int)

Nav Controller で遷移する

Nav Controller を取得したら Navigate で画面を遷移できます。
このNavigateの引数にはID指定し、どこからどこへ遷移するか指定します。
このIDですがNav Graphを設定するNavigation Editorで矢印をクリックすると確認できます。

NavController.navigate(ID)

説明したNav Controllerを取得する方法とNav Controllerで遷移する方法を組み合わせて
次のようにFragmentにコードを実装すれば画面遷移できるようになります。

Fragment.kt
class OneFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_one, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Fragment を使った Nav Controller の取得
        val navController = this.findNavController()
        val button = view.findViewById<Button>(R.id.nav_button)
        button.setOnClickListener {
            navController.navigate(R.id.action_oneFragment_to_twoFragment)
        }

        // View を使った Nav Controller の取得
        val button = view.findViewById<Button>(R.id.nav_button)
        button.setOnClickListener { view ->
            val navController = view.findNavController()
            navController.navigate(R.id.action_oneFragment_to_twoFragment)
        }
    }
}

動作確認

実装が完了したらアプリケーションをインストールして動作確認します。
ボタンをクリックすると次のFragmentに遷移できてますね。

おわりに

Navigationは複雑そうに見えますが簡単です。
これからはNavigationで簡単に早く画面遷移を実装しましょう。

参考文献