今回は、完全なサンプルとかではなくって、自分のメモ的な感じです。
調べたきっかけは、安易にアクティビティを作ろうとして、Navigation Drawer Activityというのを作ったら、画面遷移について、あまりにわからなかったことです。
で、Android デベロッパーの公式サイト見ると
https://developer.android.com/guide/navigation/
詳細トピックの下にずらーっていろんな項目が並んで、なんか小難しそうな感じじゃないですか!!?
ナビゲーショングラフって言われても、グラフ??棒グラフ?円グラフ?とかでわかりにくいじゃないですか。
しかし、恐れることはありません。
めっちゃ端的に、このナビゲーションで何が便利になったのか、一言でいうと、
画面遷移をxmlで定義することができる
だと思います。
今回も、Googleさんが用意してくれている、Code Labがよいです。英語ですけどね!
かいつまんで例を説明します。なお、下記のサンプルコードはこのCodeLabから拝借しています。
①あるアクティビティの中に、Fragmentが入っていて、いくつもFragmentを動かして画面遷移させる。
②Fragmentの親フラグメントみたいなのをまず作ります。
下記がその状態ですが、MainActivityのレイアウトファイルです。
my_nav_host_fragment
というFragmentのレイアウトが、親フラグメントというか、コンテナみたいな感じです。ここに、ほかのFragmentが入れ替わり立ち代わり入るということになります。
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.android.codelabs.navigation.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />
<fragment
android:id="@+id/my_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/mobile_navigation" />
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/nav_drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
③ 上記のファイルの、
app:navGraph=”@navigation/mobile_navigation”
がキモです。
mobile_navigation.xml というファイルを作ります。
ここに、画面遷移をxmlで定義します。
<?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"
app:startDestination="@+id/home_dest">
<fragment
android:id="@+id/home_dest"
android:name="com.example.android.codelabs.navigation.HomeFragment"
android:label="@string/home"
tools:layout="@layout/home_fragment">
<action
android:id="@+id/next_action"
app:destination="@id/flow_step_one_dest"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
</fragment>
<fragment
android:id="@+id/flow_step_one_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_one_fragment">
<argument
android:name="flowStepNumber"
app:argType="integer"
android:defaultValue="1"/>
<action
android:id="@+id/next_action"
app:destination="@+id/flow_step_two_dest">
</action>
</fragment>
<fragment
android:id="@+id/flow_step_two_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_two_fragment">
<argument
android:name="flowStepNumber"
app:argType="integer"
android:defaultValue="2"/>
<action
android:id="@+id/next_action"
app:popUpTo="@id/home_dest">
</action>
</fragment>
<!--中略-->
</navigation>
Fragmentの中に、actionがありますが、actionが画面遷移さきです。アクションというのが画面遷移だと思ってみてください。
たとえばHomeFragmentという画面から、ボタンを押したらFlowStepFragmentに行きたい場合、まずHomeFragment内にアクションを決めておきます。
<fragment
android:id="@+id/home_dest"
android:name="com.example.android.codelabs.navigation.HomeFragment"
android:label="@string/home"
tools:layout="@layout/home_fragment">
<action
android:id="@+id/next_action"
app:destination="@id/flow_step_one_dest"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
</fragment>
下記の部分が重要で、このflow_step_one_destってのが、
android:id="@+id/next_action"
app:destination="@id/flow_step_one_dest"
すぐ下にある
<fragment
android:id="@+id/flow_step_one_dest"
android:name="com.example.android.codelabs.navigation.FlowStepFragment"
tools:layout="@layout/flow_step_one_fragment">
<argument
android:name="flowStepNumber"
app:argType="integer"
android:defaultValue="1"/>
<action
android:id="@+id/next_action"
app:destination="@+id/flow_step_two_dest">
</action>
</fragment>
なんですよ。HomeFragment.kt内で下記のようにすれば、
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val button = view.findViewById<Button>(R.id.navigate_destination_button)
button?.setOnClickListener {
findNavController().navigate(R.id.flow_step_one_dest, null)
}
//後略
}
ボタンを押したらFlowStepFragmentに遷移します。
同じことが、下記のようにしてもできます。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val button = view.findViewById<Button>(R.id.navigate_destination_button)
button?.setOnClickListener {
// findNavController().navigate(R.id.flow_step_one_dest, null)
val action = HomeFragmentDirections.nextAction()
findNavController().navigate(action)
}
//後略
}