概要
Android Jetpackに含まれるNavigation componentを使うと、画面間の遷移を実装する上で複雑になりがちな点を軽減できる。今回は、このコンポーネントを使って簡単な画面遷移を実装してみる。
環境
Android Studio 3.5.1
準備
build.gradle(app)に以下の依存を追加する。
dependencies { ... implementation 'androidx.navigation:navigation-fragment-ktx:2.1.0' implementation 'androidx.navigation:navigation-ui-ktx:2.1.0' .... }
ライブラリーのバージョンはブログ執筆時点での最新バージョンのため、必要に応じて適宜更新してほしい。
ナビゲーションの追加
プロジェクトのres
フォルダの下に新たにnavigation
フォルダを作成し、ナビゲーションリソースxmlを追加する。ここでは、公式サンプルに倣ってnav_graph.xml
という名前にした。このファイルを選択すると下記のような画面が立ち上がる。ここでは、Fragmentを2つ作り、1つ目のFragmentから2つ目のFragmentへ遷移を示す矢印を引いている。
xmlは以下のようになっている。
nav_graph.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" android:id="@+id/nav_graph.xml" app:startDestination="@id/myFragment"> <fragment android:id="@+id/myFragment" android:name="com.zawapro.navigationcomponentlesson.MyFragment" android:label="fragment_my" tools:layout="@layout/fragment_my" > <action android:id="@+id/action_myFragment_to_myFragment22" app:destination="@id/myFragment2" /> </fragment> <fragment android:id="@+id/myFragment2" android:name="com.zawapro.navigationcomponentlesson.MyFragment2" android:label="fragment_my_fragment2" tools:layout="@layout/fragment_my_fragment2" /> </navigation>
上記の過程で、ナビゲーションエディタから2つのFragmentが作られる。これらのxmlを下記のように編集する。
1つ目は画面右下にボタンがあるFragment。
fragment_my.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorPrimary" tools:context=".MyFragment"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" android:layout_marginRight="16dp" android:layout_marginBottom="16dp" android:text="Button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
もう一つは遷移先の画面で、特に何もない画面である。
fragment_my_frgment2.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/design_default_color_primary" tools:context=".MyFragment2"/>
次に、Activityが読み込むレイアウトファイルactivity_main.xml
を下記のように変更する。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <fragment 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_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph"> </fragment>
fragment
タグを使い、全面にFragmentを配置している。ポイントは6行目でNavHostFragment
を指定しているところである。このようにしておくと、NavHostFragmentは11行目app:navGraph
で指定したidのナビゲーションリソースを読み込み、それに従った画面とナビゲーションを構築してくれる。10行目ではapp:defaultNavHost="true"
としている。このようにすることで、デフォルトの画面から遷移した後、バックキーを押すとその画面に戻ってくることができる。
ここまで出来たら画面の遷移のコードを書こう。先のnav_host.xml
にて初期画面をMyFragmentに設定していた。そこで、MyFragmentのコードを以下のように編集する。
MyFragment.kt
class MyFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_my, container, false).also { layout -> layout.findViewById<Button>(R.id.button).setOnClickListener { // NavControllerを呼び出し、アクションを指定して遷移する findNavController().navigate(R.id.action_myFragment_to_myFragment22) } } } }
inflater.inflate(R.layout.fragment_my, container, false)
にalso()
で処理を追加している。その中では、findNavController()
でNavControllerを取得し、そのnavigate()
メソッドを使いアクション先を指定する。こうすると、指定した先の画面へと遷移が行われる。
以上がNavigation componentの使い方のサンプルである。
ここまでのソースをgithubにアップしたので、参考にしてほしい。