kotlinにおけるFragment間の遷移を制御するNavigationの使い方、実装方法についてまとめていきます。
この記事の内容
公式のドキュメントやトレーニング「Android Kotlin の基礎」のレッスン3「ナビゲーション」を参考に実装のポイントとエッセンスをまとめていきます。
そもそもNavigationとは何か、という点については触れません。
前提知識
- kotlinの基礎的な文法
- AndroidStudioの使い方/アプリの作り方
- 画面や画面部品の配置方法
開発環境
- Windows 10 Home
- Android Studio 4.2.1
作成するサンプル
3つの画面を持ち、ボタンクリックにより画面遷移を行うごく簡単なアプリを作成します。
まったく意味のないアプリですが、画面間の遷移はNavigationでコントロールすることを目標とします。
GetStarted
それでは作業に取り掛かりましょう。
まずはFragmentの作成から。
build.gradel(app)の更新
事前準備としてDataBindingを有効にしておきます。
build.gradle(app) ファイルを開き、plugin、android、dependencies各ブロックに以下の通り追記してください。
plugins {
// (略)
id 'kotlin-kapt'
id 'androidx.navigation.safeargs'
}
android {
// (略)
buildFeatures {
dataBinding true
}
}
dependencies {
// (略)
implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
}
build.gradle(Project)の更新
今度はプロジェクトレベルの build.gradle ファイルを開き、ext、dependencies各ブロックに以下の通り追記します。
ext {
// (略)
navigationVersion = "2.3.0"
}
dependencies {
// (略)
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigationVersion"
}
Fragmentの作成
AndroidStudioでEmptyプロジェクトを新規作成したら layout フォルダを右クリックし、 New→Fragment→Fragment(Blank) を選択します。
名前(Fragment Name)は何でも良いのですがここでは StarFragment としておきます。Fragment Layout Nameは入力内容に応じ自動で設定されます(この場合は fragment_start となります)。
レイアウトファイルと合わせて StartFragment.kt ファイルが java フォルダ内に自動で生成されます。
作成した fragment_start には適当にButtonを作成しておきます。
同様に SecondFragment 、FinalFragment も作成しておきしょう。
レイアウトファイルの設定
作成したレイアウトファイルを開きます。親のビューにカーソルを当て、WindowsならAlt+Enter、MacならOption+Enterを押します。
Convert to data binding layoutをクリックすると自動でレイアウトファイルがDataBinding用のものに変換されます。

この設定をしておかないと次のタスクでFragmentのBindingオブジェクトが作成できないので注意してください。
Fragment.ktファイルの設定
作成した fragment_start.xml に対応する StartFragment.kt ファイルを開きます。
なんか自動生成されたコードが色々とうざったいのでclassブロックの中身全部消しちゃってください。
Fragment.ktファイルではonCreateViewをoverrideする必要があるので実装します。
下記の通りBindingオブジェクトを生成し、そのrootであるViewを返すコードを実装してください。
class StartFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val binding = DataBindingUtil.inflate<FragmentStartBinding>(
inflater,
R.layout.fragment_start,
container,
false
)
return binding.root
}
}
同じ要領で SecondFragment 、FinalFragment も編集してあげましょう。
activity_main.xmlの編集
プロジェクト作成時に自動生成される activity_main.xml が空っぽのままなので StartFragment と紐づけてあげます。
android:nameには自身のパッケージから設定してあげてください。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="@+id/startFragment"
android:name="com.warpstudio.android.navigationsample.StartFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
</layout>
この段階で試しにアプリを起動してみましょう。
StartFragment の画面が表示されるはずです。
が、この段階ではボタンをクリックしても何も起こりません(何も実装していないからね)。
次の章では画面遷移を実装していきます。
Navigationの定義
前章で作成した画面間の遷移を制御するNavigationを定義していきます。
NavigationGraphの作成
res フォルダを右クリックし、 New→Android Resource File を選択します。
ファイル名は navigation 、Resource typeは Navigation をそれぞれ設定してください。 res フォルダ直下に navigation フォルダが作成され、その中に navigation.xml というファイルがあるはずです。
activity_main.xmlの(再)編集
編集したばかりの activity_main.xml ですが、早くも更新をします。
先ほどはFragmentとの紐づけを行いましたが、ここではNavHostManagerと紐づけます。
android:name、app:navGraph、app:defaultNavHostを下記の通り設定します。
<fragment
android:id="@+id/startNavHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/navigation"
app:defaultNavHost="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Fragmentの配置
NavigationGraphに作成済のFragmentを配置していきます。 navigation.xml をデザインビューで開きます。
New Destinationボタンをクリックし、StartFragment から FinalFragment まで3つのFragmentを配置します。
なおプレビューがPreview Unavailableと表示され、見れない場合は navigation.xml をコードビューで開き、各FragmentのTool属性を下記の通り設定してあげます。
<fragment
android:id="@+id/startFragment"
android:name="com.warpstudio.android.navigationsample.StartFragment"
android:label="StartFragment"
tools:layout="@layout/fragment_start"/>
Destinationの設定
配置したFragment間の遷移を定義します。デザインビューでFragmentをクリックすると右側から矢印が伸ばせるので遷移対象のFragmentに結びます。
この操作により自動でナビゲーションのidとDestinationが設定されます。画面遷移にはこのidを利用します。
こんな感じになりました。

ClickHandlerの実装
StartFragment を開きClickHandlerを実装します。
binding.startButton.setOnClickListener {view: View ->
view.findNavController().navigate(R.id.action_startFragment_to_secondFragment)
}
同様に SecondFragment 、FinalFragment のボタンにもDestinationに従いリスナを登録します。
これによりボタンのクリックにより画面遷移が行われるようになりました。
アプリを起動して確認してみてください。
Fragment間で引数を渡す
前章までがFragmentの基本的な実装方法となりますが、Fragment間で引数を扱いたいケースもあると思います。
その実装方法として推奨されているのがSafeArgsです。
ClickHandlerの改修
前章の最後で実装したClickHandlerを下記の通り改修します。
binding.startButton.setOnClickListener { view : View ->
view.findNavController().navigate(StartFragmentDirections.actionStartFragmentToSecondFragment())
}
従来はidから呼び出していたactionをNavDirectionクラスから呼び出す方式に変更しています。
同様に残りのFragmentも改修しましょう。
引数の設定
navigation.xml で定義したFragment間のPathに引数の情報を加えます。
引数を受け取りたいFragmentを選択した状態でデザインビュー右側のAttributeペインの Arguments を開いてください。
**+**ボタンをクリックすると下記のダイアログが表示されるので引数として設定する変数の名前と型を登録します。

異なる型の引数を複数設定することもできますよ。
ClickHandlerの改修(その2)
またもやClickHandlerのメンテナンスです。
上記の状態でコンパイルしようとしてもエラーが出るのですが、それは遷移元のFragmentがnavigateする際に必要な引数を与えていないからですね。
今回は StartFragment から SecondFragment の遷移にあたりIntegerとStringの引数を設定しました。
なのでClickHandlerは下記の通りとなります。
val args1: Int = 1
val args2: String = "hoge"
binding.startButton.setOnClickListener { view : View ->
view.findNavController()
.navigate(StartFragmentDirections
.actionStartFragmentToSecondFragment(args1, args2))
}
遷移先のFragmentの処理
遷移先のFragmentでは以下の方法で引数を受け取ることができます。
val args = SecondFragmentArgs.fromBundle(requireArguments())
val args1 = args.argsInt
val args2 = args.argsStr
Recap
今回の記事は以上となります。
読んでいただいた方は長丁場ありがとうございました。
ご覧の通り、FragmentやNavigationの概念的な内容について触れてはおりませんので、深く学習したい方は公式のドキュメントをぜひ参照してください。
また実際には戻るボタンの制御やここにViewModelが加わったらどうなるのか等、実務レベルでは不十分な点もあるかと思います。
ただコーディングの際、「あれ、ここどうやって書くんだっけ」ってなったときなど、クイックリファレンス的な使い方でお役に立てれば嬉しいですね。
ではまた。