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
が加わったらどうなるのか等、実務レベルでは不十分な点もあるかと思います。
ただコーディングの際、「あれ、ここどうやって書くんだっけ」ってなったときなど、クイックリファレンス的な使い方でお役に立てれば嬉しいですね。
ではまた。