NavGraphが分割されたFragmentに対して直接遷移したい(Navigation DeepLink)

1 min read読了の目安(約1600字

背景

  • メニュー画面とメインフローでnavGraphを分割した
  • しかし、その後メインフローでメニューの詳細機能へのショートカットボタンが追加された
  • メニュー画面を経由させずにメニューの詳細機能画面へ遷移したい
  • でも単にnavGraphをincludeするだけだとメニュー画面(startDestination)にしか遷移できない

方法

NavigationのDeepLinkを利用する

実装

1. deeplinkのタグを遷移先のFragmentに追加する

遷移先navigation.xml

    <fragment
        android:id="@+id/sennisakiFragment"
        android:name="example.SennisakiFragment"
        android:label="SennisakiFragment">
        <deepLink
            android:id="@+id/to_sennisaki"
            app:uri="example://menu/sennisaki" />
    </fragment>

2. 遷移元のnavGraphに遷移先のnavGraphをincludeする

遷移元navigation.xml

....
    <include app:graph="@navigation/遷移先navigation" />
</navigation>

3. ショートカットタップ時にDeepLinkする

	// 別にNavDeepLinkRequestを作らなくても、navController.navigate(Uri.parse("example://menu/sennisaki"))でも大丈夫
        val navDeepLinkRequest = NavDeepLinkRequest.Builder
            .fromUri(Uri.parse("example://menu/sennisaki"))
            .build()

	// どこに戻ってくるかとか、singleTopでしたいとかを設定したいときはnavOptionsを利用する
        val navOptions = NavOptions.Builder()
            .setPopUpTo(R.id.sennimotoFragment, false)
            .build()

	findNavController().navigate(navDeepLinkRequest, navOptions)

これでOK。

補足

  • 利用するnavControllerはもちろんincludeしたnavGraphのnavControllerを使う
  • もしnavGraphの中のFragmentがさらにnavGraphを持っていた場合などは以下のようにfindFragmentByIdとかでとってくると良いかも。
        childFragmentManager.findFragmentById(R.id.nakano_nav_host)?.let {
            val navController = NavHostFragment.findNavController(it)
            navController.navigate(navDeepLinkRequest, navOptions)
        }

感想

情報が少なすぎて半日かかったよ。。