LoginSignup
19
8

More than 3 years have passed since last update.

Navigation Compose を使ってみる

Last updated at Posted at 2020-10-29

Jetpack Compose で画面遷移する仕組みとして Navigation Compose が用意されています。
stable になるまで大きな変更が入るそうですが、1.0.0-alpha01 時点でどのように使うのか、内部でどのようなことをしているのか書いていこうと思います。

実装

セットアップ

dependencies {
    implementation "androidx.navigation:navigation-compose:1.0.0-alpha01"
}

ライブラリへの依存を追加します。

画面の定義

Screen.kt

@Composeable
fun App() {
    val navController = rememberNavController()
    NavHost(navController, startDestination = "profile") {
        composable("profile") { ProfileScreen(...) }
        composable("friends") { FriendsScreen(...) }
    }
}

Composable の NavHostrememberNavController で最初の画面や遷移先の画面を設定していきます。
NavHost 内の composable で設定した文字列をキーに画面へ遷移することになります。

遷移処理

Button(
    onClick = { 
        navController.navigate("friends") 
    }
) {
    Text(text = "Navigate next")
}

NavHostController#navigate で遷移したい画面の composable に定義した文字列を渡すことで画面遷移を行います。

前の画面に戻る際は NavHostController#popBackStack を使います。

遷移時に値を渡す

NavHost(...) {
    ...
    composable(
        route = "friend/{friendId}",
        arguments = listOf(navArgument("friendId") { type = NavType.StringType })
    ) {...}
}

NavHost 内の composable の文字列に渡したい値のプレースホルダーを定義します。
そして arguments に渡したい値と型の定義をします。

composable(
    route = "friend/{friendId}",
    arguments = listOf(navArgument("friendId") { type = NavType.StringType })
) { backStackEntry ->
    Friend(navController, backStackEntry.arguments?.getString("friendId"))
}

composable の中で定義した Composable の画面で NavBackStackEntry#arguments から値を取り出せます。
(Parcelable や Serializable どうするんだろ…)

Navigation Compose の実装をみてみる

内部でどのようにして画面遷移を実現しているのかライブラリのコードをみてみましょう。

public fun NavGraphBuilder.composable(
    route: String,
    arguments: List<NamedNavArgument> = listOf(),
    deepLinks: List<NavDeepLink> = listOf(),
    content: @Composable (NavBackStackEntry) -> Unit
) {
    addDestination(
        ComposeNavigator.Destination(provider[ComposeNavigator::class], content).apply {
            val internalRoute = createRoute(route)
            addDeepLink(internalRoute)
            val argument = navArgument(KEY_ROUTE) { defaultValue = route }
            addArgument(argument.component1(), argument.component2())
            id = internalRoute.hashCode()
            arguments.forEach { (argumentName, argument) ->
                addArgument(argumentName, argument)
            }
            deepLinks.forEach { deepLink ->
                addDeepLink(deepLink)
            }
        }
    )
}

NavHost 内の composable のコードです。
composable に引数に渡した文字列を createRoute に渡して、 "android-app://androidx.navigation.compose/$route" というリンクを生成して DeepLink として設定しています。
値を渡す時にプレースホルダーを使った時点でなんとなく察することができそうですが、Jetpack Navigation の DeepLink の仕組みを使って Jetpack Compose の画面遷移を実現しているようです。

これまでの Jetpack Navigation の知識をそのままに Jetpack Compose でも遷移できるようになっているので、新しく知ることも少なくすみ移行もしやすそうですね。

19
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
8