Android jetpack Navigationについて簡単な説明

今回は、完全なサンプルとかではなくって、自分のメモ的な感じです。

調べたきっかけは、安易にアクティビティを作ろうとして、Navigation Drawer Activityというのを作ったら、画面遷移について、あまりにわからなかったことです。

で、Android デベロッパーの公式サイト見ると

https://developer.android.com/guide/navigation/

詳細トピックの下にずらーっていろんな項目が並んで、なんか小難しそうな感じじゃないですか!!?
ナビゲーショングラフって言われても、グラフ??棒グラフ?円グラフ?とかでわかりにくいじゃないですか。

しかし、恐れることはありません。

めっちゃ端的に、このナビゲーションで何が便利になったのか、一言でいうと、

画面遷移をxmlで定義することができる

だと思います。

今回も、Googleさんが用意してくれている、Code Labがよいです。英語ですけどね!

https://codelabs.developers.google.com/codelabs/android-navigation/index.html?index=..%2F..%2Findex#0

かいつまんで例を説明します。なお、下記のサンプルコードはこの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)
        }
//後略
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です