Jetpack Navigation コンポーネント

依存関係

ロジェクト レベルの build.gradle
[buildscript] > [ext] で、material_version の nav_version を 2.3.1 に設定し
classpathを追加

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”
}

dependencies {
….
classpath “androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version”
}

}

アプリレベルの build.gradle
プラグインと依存関係を追加
plugins {
….
id ‘androidx.navigation.safeargs.kotlin’
}
dependencies {
implementation “androidx.navigation:navigation-fragment-ktx:$nav_version”
implementation “androidx.navigation:navigation-ui-ktx:$nav_version”
}

ナビゲーショングラフのセットアップ

[File] > [New] > [Android Resource File]
File Name:nav_graph.xml。activity_main.xmlのapp:navGraph 属性に設定する名前と同じもの
ResouceType:Navigation

ナビゲーショングラフの設定

+ボタンでフラグメントを追加
画面遷移をドラッグして指定
開始フラグメントを選択してStartDistnationボタンを押下(家のアイコン)
必要に応じて遷移先のフラグメントでArgumentsを追加
メニューバーのタイトルはandroid:labelで指定する

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

    <fragment
        android:id="@+id/letterListFragment"
        android:name="com.example.wordsapp.LetterListFragment"
        android:label="@string/app_name">
        <action
            android:id="@+id/action_letterListFragment_to_wordListFragment"
            app:destination="@id/wordListFragment" />
    </fragment>
    <fragment
        android:id="@+id/wordListFragment"
        android:name="com.example.wordsapp.WordListFragment"
        android:label="@string/word_list_fragment_label">
        <argument
            android:name="letter"
            app:argType="string" />
    </fragment>
</navigation>

activity_main.xml

フラグメントを表示するためFragmentContainerViewを追加する
・idはnav_host_fragment
・name属性に以下を設定
android:name=”androidx.navigation.fragment.NavHostFragment”
・コンテナ間でシステムの戻るボタンなどを有効にするため以下を設定
app:defaultNavHost=”true”
※appのnsはxmlns:app=”http://schemas.android.com/apk/res-auto”
・ナビゲーショングラフファイルの設定
app:navGraph=”@navigation/nav_graph”

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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: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>

アクティビティ(MainActivity)

フラグメントとナビゲーション設定
・activity_main.xmlに定義したFragmentContainerViewを取得
・ナビゲーションコントローラーを取得
・アプリバーの表示、上へボタンなどの設定

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupActionBarWithNavController

class MainActivity : AppCompatActivity() {
    // ナビゲーションコントローラー
    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // ナビゲーション設定
        // activity_main.xmlに定義したFragmentContainerViewを取得
        val navHostFragment = supportFragmentManager
            .findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        // ナビゲーションコントローラーを取得
        navController = navHostFragment.navController
        // アプリバーを表示
        setupActionBarWithNavController(navController)
    }

    // 上へボタンを有効
    override fun onSupportNavigateUp(): Boolean {
        return navController.navigateUp() || super.onSupportNavigateUp()
    }
}

遷移元画面の設定

・アクションと引数を取得
 {遷移元のフラグメント名+Directions}.{navグラフのid名}(引数 key=値)
・NavControllerへアクションを渡し navigate()を呼び出し

override fun onBindViewHolder(
    holder: LetterViewHolder,
    position: Int) {
    val item = list.get(position)
    holder.button.text = item.toString()

    // ワードボタンのクリックリスナー
    holder.button.setOnClickListener{
        // アクションの定義と引数を取得
        // {遷移元のフラグメント名 + Directions }.{navグラフのid名}(引数 key=値)
        val action = LetterListFragmentDirections.actionLetterListFragmentToWordListFragment(letter = holder.button.text.toString())
        // アクションを設定
        holder.view.findNavController().navigate(action)
    }
}

フラグメントからの画面遷移例

import androidx.navigation.fragment.findNavController
// findNavController().navigate(R.id.(navコントローラーの矢印のID))
findNavController().navigate(R.id.action_startFragment_to_flavorFragment)

遷移先画面の設定

fragmentのonCreate等で引数を取得

// Fragment起動時に引数で取得したパラメータを格納する変数
private lateinit var letterId: String

// 1.onCreate
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // 引数の取得
    arguments?.let {
        letterId = it.getString(LETTER).toString()
    }
}

トレーニング > KOTLIN を用いた ANDROID の基本 > ナビゲーション > ナビゲーションの概要 > フラグメントとナビゲーションコンポーネント > 7. Jetpack Navigation コンポーネント