Navigationのセットアップ&使い方(Kotlin)

## はじめに

Navigationのセットアップ方法と使い方を紹介します。

## 「Navigation」とは？

Googleが提供しているJetpackのコンポーネントです。
フラグメント間の遷移など、様々なナビゲーションの実装に役立ちます。

## 環境

- OS：macOS Big Sur 11.5.2
- Android Studio：Arctic Fox | 2020.3.1
- Kotlin：1.5.21
- Gradle：7.0.2
- Gradle plugin：7.0.0
- Navigation：2.3.5

## セットアップ

### Navigationのインストール

ルート直下の「build.gradle」にNavigationのバージョンを追加します。

別の記事で紹介する予定ですが、Navigationと併用して「Safe Args」というGradleプラグインを使うことが多いです。
そのため、先にNavigationのバージョンを定数化しています。

```diff_groovy:/build.gradle
buildscript {
    ext {
+       nav_version = '2.3.5'
    }
}
```

appフォルダ配下の「build.gradle」に依存関係を追加します。

```diff_groovy:/app/build.gradle
dependencies {
+   // Navigation
+   implementation "androidx.navigation:navigation-fragment-ktx:$rootProject.nav_version"
+   implementation "androidx.navigation:navigation-ui-ktx:$rootProject.nav_version"
}
```

これでNavigationのセットアップは完了です。

## 用語

Navigationに使われる用語を紹介します。

|用語|説明|
|:--|:--|
|ナビゲーション|デスティネーション間の移動|
|デスティネーション|アプリ内で移動できる場所（アクティビティやフラグメント）|
|アクション|デスティネーション間の接続|

## 使い方

### ナビゲーショングラフの作成

ナビゲーショングラフとは、デスティネーションとアクションを格納するリソースファイルです。

__Project > `res` フォルダで右クリック > New > Android Resource File__
![スクリーンショット_2021-08-20_16_57_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/e57f817a-38ff-711f-5192-5c43066dfe20.png)

File nameに `nav_graph` のような名前を入力します。ナビゲーショングラフを複数作成する場合は `○○_nav_graph` と命名するといいです。
Resource typeに「Navigation」を選択し、「OK」ボタンを押下します。
![スクリーンショット_2021-08-17_21_00_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/fd581fb8-ed6b-25c4-40e9-77b3d1eae68c.png)

### ナビゲーショングラフの実装

ナビゲーショングラフのファイルを作成したら、中身を実装します。

以下は `MainFragment` から `OssLicensesMenuActivity` へ遷移するだけの、シンプルなナビゲーショングラフです。

```xml:nav_graph.xml
<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/main_fragment">

    <fragment
        android:id="@+id/main_fragment"
        android:name="com.theuhooi.uhooipicbook.ui.main.MainFragment"
        android:label=""
        tools:layout="@layout/main_fragment">
        <action
            android:id="@+id/action_main_to_licenses"
            app:destination="@id/licenses_activity" />
    </fragment>

    <activity
        android:id="@+id/licenses_activity"
        android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity" />

</navigation>
```

ナビゲーションやフラグメント、アクティビティは `id` を付けて識別します。
初期表示するデスティネーションは `app:startDestination` に `id` で指定します。

Android Studioが自動でプレビューしてくれるので、とてもわかりやすいです。
矢印がアクションです。
![スクリーンショット 2021-08-20 17.19.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138245/43964f5c-53b0-2c24-c49a-e7e319467191.png)

### アクティビティにナビゲーションホストを追加する

ナビゲーショングラフを実装したら、アクティビティにナビゲーションホストを追加します。
ナビゲーションホストは空のコンテナであり、遷移するたびにコンテナ内でデスティネーションが入れ替わります。

ここでは開始のデスティネーションとして指定した `MainFragment` の親である `MainActivity` にナビゲーションホストを全体表示します。

```xml:main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/container"
    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="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/nav_graph" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

これで `MainFragment` を表示できます。

### ナビゲーション処理の実装

`MainFragment` から `OssLicensesMenuActivity` へのナビゲーション処理を実装します。

Safe Argsのセットアップが必要なので、以下の記事を参考に行ってください。
https://qiita.com/uhooi/items/b73911afdc62ae188a3b

ナビゲーショングラフから自動で `MainFragmentDirections.actionMainToLicenses()` というメソッドが生成されるので、その戻り値（アクション）を `findNavController().navigate()` メソッドの引数に渡して呼び出すのみです。

```kotlin:MainFragment.kt
class MainFragment : Fragment() {
    fun foo() {
        findNavController().navigate(MainFragmentDirections.actionMainToLicenses())
    }
}
```

これだけでナビゲーション処理が実装できます。

## おわりに

Navigationを使うことで、フラグメントやアクティビティ間の画面遷移をかんたんに実現できました！

## 参考リンク

- [ナビゲーション  |  Android デベロッパー  |  Android Developers](https://developer.android.com/guide/navigation?hl=ja&authuser=1)
- [Navigation コンポーネント スタートガイド  |  Android デベロッパー  |  Android Developers](https://developer.android.com/guide/navigation/navigation-getting-started?hl=ja&authuser=1#groovy)