はじめに
今回はAndroid JetPackのNavigationについてまとめました。
「これからNavigationに移行しようと思ってるけどどうやれば...」
「Navigationってそもそもなんぞや」
という方向けの記事になります。
Navigaiton とは
アプリの画面遷移をサポートするライブラリです。
特徴として、
- アプリの画面遷移を手軽に実装できる
- 視覚的に画面遷移の動線を確認できる
- GUIから設定が可能
があり、かなり直感的に画面遷移の設定をすることができます。
サンプルアプリ
Navigationの基礎機能を確認するためにサンプルアプリを取得しましょう。
今回はarchitecture-conponents-sampleの中にあるNavigationBasicSampleを使用します。
なおこのリポジトリはAndroid-Architecture-ComponentsというモダンなAndoridアプリ開発を手助けしてくれるライブラリ群全体のサンプルコードがありますので、ぜひ他のコードも見てみてください。
Navigation Graphの設定
サンプルコードのnavigation.xmlがNavigation Graphになります。
ここには画面遷移させたいActivity, Fragmentを記述することで、コードからNavigationを設定することができるようになります。
<!-- app:startDestinationで指定したFragmentが自動的にbackstackの一番下(最初に起動するFragment)になる -->
<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"
app:startDestination="@+id/title_screen">
<!-- fragmentタグを使ってFragmentを指定 -->
<!-- activityタグもあるので、別Activityに飛びたい時はactivityタグを指定する -->
<fragment
android:id="@+id/title_screen"
android:name="com.example.android.navigationsample.TitleScreen"
android:label="fragment_title_screen"
tools:layout="@layout/fragment_title_screen">
<action
android:id="@+id/action_title_screen_to_register"
app:destination="@id/register"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"/>
<action
android:id="@+id/action_title_screen_to_leaderboard"
app:destination="@id/leaderboard"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"/>
</fragment>
<!-- 略 -->
</navigation>
他タグの属性に関しては下でさらに説明させていただきます。
actionを使った画面遷移
fragmentタグの下にactionタグを設定することで、対象のFragmentからの画面遷移を設定することができます。
<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"
app:startDestination="@+id/title_screen">
<fragment
android:id="@+id/title_screen"
android:name="com.example.android.navigationsample.TitleScreen"
android:label="fragment_title_screen"
tools:layout="@layout/fragment_title_screen">
<!-- ここで設定 -->
<action
<!-- 固有のIDを指定 -->
android:id="@+id/action_title_screen_to_register"
<!-- 遷移先のIDをここで指定 -->
app:destination="@id/register"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"/>
<!-- 略 -->
</fragment>
<fragment
android:id="@+id/register"
android:name="com.example.android.navigationsample.Register"
android:label="fragment_register"
tools:layout="@layout/fragment_register">
<action
android:id="@+id/action_register_to_match"
app:destination="@id/match"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"/>
</fragment>
<!-- 略 -->
</navigation>
Nav Graphでactionの設定ができたらこれを遷移元のFragmentから呼び出します
// 基本的な呼び方
Navigation.findNavController(view).navigate(R.id.action_title_screen_to_register)
// ktxを使うと短くなる
findNavController().navigate(R.id.action_title_screen_to_register)
たったこれだけで画面遷移の実装をすることができます。
しかもBackStackも自動で積まれているので、遷移先からバックキーで戻ると遷移元に戻ることができます。
Transitions
actionタグから遷移時のアニメーションを設定することができます。
<action
android:id="@+id/action_title_screen_to_register"
app:destination="@id/register"
<!-- ここで設定 -->
<!-- 戻るアクションにより表示されるときのアニメーション -->
app:popEnterAnim="@anim/slide_in_left"
<!-- 戻るアクションにより非表示になるときのアニメーション -->
app:popExitAnim="@anim/slide_out_right"
<!-- 画面遷移により表示されるときのアニメーション -->
app:enterAnim="@anim/slide_in_right"
<!-- 画面遷移により非表示になるときのアニメーション -->
app:exitAnim="@anim/slide_out_left"/>
サンプルアプリでは横にスライドしていくようなアニメーションになっていますが、独自アニメーションを設定することで画面遷移の体験を変えることもできます。
遷移時の引数
Safe Argsを使用することで、遷移元から遷移先に値を渡すことができます。
<fragment
android:id="@+id/user_profile"
android:name="com.example.android.navigationsample.UserProfile"
android:label="fragment_user_profile"
tools:layout="@layout/fragment_user_profile">
<!-- ここで設定 -->
<!-- 複数設定したい場合にはargumentタグを並べていくと設定可能 -->
<argument android:name="userName"
<!-- argTypeで型の設定が可能 -->
<!-- defaultValueの設定も可能 -->
android:defaultValue="name"/>
</fragment>
設定ができたらFragmentから呼び出します。
holder.item.setOnClickListener {
val bundle = bundleOf("userName" to myDataset[position])
Navigation.findNavController(holder.item).navigate(
R.id.action_leaderboard_to_userProfile,
bundle
)
}
DeepLinkの指定
DeepLinkの設定をすることで、指定したLinkからアプリを起動すると対象のFragmentを直で起動させることができます。
<fragment
android:id="@+id/user_profile"
android:name="com.example.android.navigationsample.UserProfile"
android:label="fragment_user_profile"
tools:layout="@layout/fragment_user_profile">
<argument android:name="userName"
android:defaultValue="name"/>
<!-- ここで設定 -->
<!-- argumentがある場合にはそれをDeepLinkに指定することで遷移ができるようになる -->
<!-- 逆に指定しないと引数なしでクラッシュするので注意 -->
<deepLink app:uri="www.example.com/user/{userName}" />
</fragment>
終わりに
今回はNavigationについてまとめてみました。
記事の中ではNav Graphに直接記載する形で設定をしましたが、AndoridStudio 3.3以上からはGUIからの設定も可能になっており、なお一層直感的に設定ができるようになっています。
参考資料
サンプルコード
https://github.com/android/architecture-components-samples/tree/main/NavigationBasicSample
Navigationの公式リファレンス
https://developer.android.com/jetpack/androidx/releases/navigation?hl=ja