はじめに
Jetpack
のNavigation
で Safe Args
を使って、
パラメータを渡せるサンプルをサクッと実装したいと思います。
準備
Navigation
をセットアップする
Navigation
を利用したアプリケーションを作成するための下準備をします。
次の手順で必要なライブラリやクラス、レイアウトを生成していきます。
dependencies {
def nav_version = "2.1.0"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}
Fragment
を作成する
Navigation
を使った遷移で利用する Fragment
を作成していきます。
次の手順で OneFragment
, TwoFragment
, ThreeFragment
の 3つを作成します。
-
Package Name
を右クリックし、New → Fragment → Fragment(Blank)
を選択する -
Fragment Name
に任意の名称
を入力しOK
を押す -
Fragment
にいらない記述が書かれているので消す -
Layout
にFragment
に遷移させるためのButton
を追加する -
Layout
にFragment
を遷移させたときのパラメータを表示されるTextView
を追加する
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)
}
}
<?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">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="50dp"/>
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="bottom"
android:text="Next" />
</FrameLayout>
Safe Args
をセットアップする
あと今回はSafe Args
を利用したアプリケーションを作成するので、
Safe Args
が利用できるようにセットアップします。
この設定をするとSafe Args
で利用するクラスが自動的に生成されるようになります。
dependencies {
def nav_version = "2.1.0"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
apply plugin: "androidx.navigation.safeargs.kotlin"
実装
Safe Args
を次の 2 ステップで実装していきます。
No | 名称 | 役割 |
---|---|---|
1 |
Navigation で画面遷移させる |
Nav Host 、Navigation Graph 、Nav Controller を実装して画面遷移できるようにします。 |
2 |
Safe Args でパラメータを渡す |
Safe Args で遷移先Fragment にパラメータを渡せるようにします。 |
Step1 Navigation
で画面遷移させる
Safe Args
でパラメータを引き渡すため基本となる画面遷移を実装していきます。
Nav Graph の作成する
nav_graph.xml
を作成し、次の内容のNavigation Editor
で記述します。
Nav Graph
の作成の詳しい方法はこちらに書いてあるので参考にしてください。
<?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/oneFragment">
<fragment
android:id="@+id/oneFragment"
android:name="c.kaleidot725.safeargssample.OneFragment"
android:label="fragment_one"
tools:layout="@layout/fragment_one" >
<action
android:id="@+id/action_oneFragment_to_twoFragment"
app:destination="@id/twoFragment" />
</fragment>
<fragment
android:id="@+id/twoFragment"
android:name="c.kaleidot725.safeargssample.TwoFragment"
android:label="fragment_two"
tools:layout="@layout/fragment_two" >
<action
android:id="@+id/action_twoFragment_to_threeFragment"
app:destination="@id/threeFragment" />
</fragment>
<fragment
android:id="@+id/threeFragment"
android:name="c.kaleidot725.safeargssample.ThreeFragment"
android:label="fragment_three"
tools:layout="@layout/fragment_three" />
</navigation>
Nav Host
を作成する
Main Activity
にFragment
を表示するためのNav Host
を作成します。
<?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
を取得して画面を遷移させる
OneFragment
, TwoFragment
, ThreeFragment
で
Nav Controller
を取得して、Button
で画面遷移できるようにします。
class OneFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_one, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val b = view.findViewById<Button>(R.id.next_button)
b.setOnClickListener {
this.findNavController().navigate(R.id.action_oneFragment_to_twoFragment)
}
}
}
いまのところ、こんな感じで動作します。このアプリケーションの
画面遷移時にパラメータを引き渡せるように実装していきます。
Step2 Safe Args
でパラメータを渡す
そしてSafe Args
でパラメータを引き渡す処理を実装していきます。
Navigation Editor
にてArgument
を作成する
Navigation Editor
でFragment
にArgument Default Values
を追加して、
遷移元から遷移先に遷移するときにパラメータを指定できるようにします。
次の手順を繰り返してOneFragment
、TwoFragment
、ThreeFragment
にパラメータを指定できるようにします。
- 遷移先の
Fragment
を選択し、Attributes
のArguments
の➕
をクリックする -
Name
にtitle
、Type
をString
を選択し、ADD
をクリックする -
1
で選択したFragment
に遷移する矢印を選択し、titile
のdefault value
を設定する。
<Fragment名称>Directions
<Fragment名称>Args
が生成されているか確認する
Navigation Editor
でArgument
を作成すると画面遷移時のパラメータ受け渡しに必要となる
<Fragment名称>Directions
、<Fragment名称>Args
が自動生成されます。
<Fragment名称>Directions
は遷移元のFragment
でパラメータを指定するため、
<Fragment名称>Args
は遷移先のFragment
でパラメータを取得するのに利用します。
今回だとOneFragmentDirecitons
とOneFragmentArgs
など、
作成した3つのFragment
に対応するクラスが自動生成されているはずです。
class OneFragmentDirections private constructor() {
private data class ActionOneFragmentToTwoFragment(val title: String) : NavDirections {
override fun getActionId(): Int = R.id.action_oneFragment_to_twoFragment
override fun getArguments(): Bundle {
val result = Bundle()
result.putString("title", this.title)
return result
}
}
companion object {
fun actionOneFragmentToTwoFragment(title: String): NavDirections =
ActionOneFragmentToTwoFragment(title)
}
}
data class OneFragmentArgs(val title: String) : NavArgs {
fun toBundle(): Bundle {
val result = Bundle()
result.putString("title", this.title)
return result
}
companion object {
@JvmStatic
fun fromBundle(bundle: Bundle): OneFragmentArgs {
bundle.setClassLoader(OneFragmentArgs::class.java.classLoader)
val __title : String?
if (bundle.containsKey("title")) {
__title = bundle.getString("title")
if (__title == null) {
throw IllegalArgumentException("Argument \"title\" is marked as non-null but was passed a null value.")
}
} else {
throw IllegalArgumentException("Required argument \"title\" is missing and does not have an android:defaultValue")
}
return OneFragmentArgs(__title)
}
}
}
<Fragment名称>Directions
で遷移時にパラメータを指定する。
次のように<Fragment名称>Directions
を利用して、
画面遷移時にtitle
パラメータを指定します。
actionOneFragmentToTwoFragment
にてtitle
が指定できます。
今回はTwo Fragment
という文字列を指定しておきます。
class OneFragment : Fragment() {
val args : OneFragmentArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_one, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val b = view.findViewById<Button>(R.id.next_button)
b.setOnClickListener {
val action = OneFragmentDirections.actionOneFragmentToTwoFragment("Two Fragment")
this.findNavController().navigate(action)
}
}
}
<Fragment名称>Args
で遷移時にパラメータを取得する。
次のように<Fragment名称>Args
を利用して、
画面遷移先のFragment
にてパラメータを取得します。
TwoFragmentArgs
にてtitle
が取得できるようになっています。
今回は取得したtitile
をTextView
に表示してみます。
class TwoFragment : Fragment() {
val args : TwoFragmentArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_two, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val t = view.findViewById<TextView>(R.id.param_view)
t.text = args.title
}
}
こんな感じで画面遷移時にパラメータを渡せるようになります。
遷移先のTextView
に遷移元で指定したパラメータが表示できていますね。
おわりに
上記のサンプルを通して、Safe Args
がどのような動きをするのか、
またはどのようにすれば画面遷移時にパラメータを渡せるのか理解できました。
その内容を簡潔にまとめると次の3点になると思います。
-
Navigation
でSafe Args
を画面遷移するときにパラメータを受け渡せる。 -
Safe Args
をプロジェクトで利用するようにし、Navigation Editor
で遷移時のパラメータを設定すると、自動的にパラメータを受け渡すクラスである<Fragment名称>Directions
と<Fragment名称>Args
が生成される。 - 生成された
<Fragment名称>Directions
と<Fragment名称>Args
を利用して、Navigation
の画面遷移処理を実装すると安全にパラメータを受け渡すことができる。
Safe Args
を利用する場合のクラス体型を記載すると次のような感じです。
見てわかる通りFragment
ごとに必要なクラスが生成されるのでそれを使えばよいようになっています。