2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Jetpack Compose Navigation(Navigation Arguments, Nested Navigation)

Last updated at Posted at 2022-01-21

#目次

  1. Navigation Arguments, Nested Navigationとは
  2. サンプルコード
  3. まとめ

##1. Navigation Arguments, Nested Navigationとは

Navigation Arguments‥画面遷移時に、画面間で共有できる値。この値は、{ } (プレースホルダ)を用い、argumentsを型を指定してlistで管理できます。また、SavedStateHandleを使って、画面遷移時に必要なargumentsを取得できますが、今回は説明を省きます。

以下の実装を行います(UIの詳細については説明を省きます。)

navigation.gif

Nested Navigation‥デスティネーションを、モジュール化すること。NavigationHost以下に、NavGraphを作成することで、Navigation間の依存関係を切り離す役割を持っています。(NavHostで、呼び出すcomposableをさらにグループで分けることで実装を行います。)

以下の実装を行います(UIの詳細については説明を省きます。)

navigation2 (1).gif

##2. サンプルコード

Navigation Arguments

あるUI要素のアイテムをクリックしたときに、その要素のiteId=1を遷移後の画面に表示する実装を仮定しました。

まず、構成画面として以下の2つを仮定しました。

sealed class Screen(val route: String){

    object HomeScreen: Screen("home_screen")
    object DetailScreen: Screen("selected_screen")
}

次に、navgraphの作成をNavHostを用いて以下のように行います。

@Composable
fun NavigationSetUp(
    navController: NavHostController
){

    NavHost(
        navController = navController,
        startDestination = Screen.HomeScreen.route
    ){
        composable(
            route = Screen.HomeScreen.route
        ){
            HomeScreen(navController = navController)
        }
        composable(
            route = Screen.DetailScreen.route + "/{itemId}",
            arguments = listOf(navArgument("itemId") {
                type = NavType.StringType
            })
        ){
            val itemId = it.arguments?.get("itemId").toString()
            DetailScreen(itemId = itemId)
        }
    }
}

DetailScreen‥このコンポーザブルを呼び出しているNavHostcomposableを確認すると、routeを**{ itemId }というプレースホルダ**とともに取り扱っていることがわかります。そして、arguments内で、argumentsのタイプを決定することができ、StringTypeとしてることがわかります。

注意点として、HomeScreenでオブジェクトを指定して画面を遷移する際に、**/**の記述がないと正しく遷移が行われないので注意が必要です。

navController.navigate(route = Screen.DetailScreen.route + "/1")

以上のコードを実行すると、以下のようにできます。

navigation.gif

Nested Navigation

NavHost(
        navController = navController,
        startDestination = Screen.HomeScreen.route
    ){
        composable(
            route = Screen.HomeScreen.route
        ){
            HomeScreen(navController = navController)
        }
        composable(
            route = Screen.DetailScreen.route + "/{itemId}",
            arguments = listOf(navArgument("itemId") {
                type = NavType.StringType
            })
        ){
            val itemId = it.arguments?.get("itemId").toString()
            DetailScreen(itemId = itemId)
        }
        composable(
            route = 
        ){}
        composable(
            route = 
        ){}
        composable(
            route = 
        ){}
        composable(
            route = 
        ){}
}

上記のように、画面構成が大きくなるにつれ1つのNavHost内で遷移を管理することはとても大変になります。そこで、意味のある区分で遷移先を区分することを、Nested Navigationといいます。

それでは、サンプルコードに移ります。

@Composable
fun NavigationSetUp(
    navController: NavHostController
){
    NavHost(
        navController = navController,
        startDestination = Screen.HomeScreen.route
    ){
        composable(
            route = Screen.HomeScreen.route
        ){
            HomeScreen(navController = navController)
        }
        composable(
            route = Screen.DetailScreen.route
        ){
            DetailScreen()
        }
        composable(
            route = Screen.LogInScreen.route
        ){
            LogInScreen(navController = navController)
        }
    }
}

上記のコードを、意味のあるくくりで分割するには、navigationを使用します。navigationで、新たにstartDestination, routeを定義でき以下のように区分を行いました。

        navigation(
            startDestination = Screen.LogInScreen.route,
            route = AUTHENTICATE_ROUTE,
        ){
            composable(
                route = Screen.LogInScreen.route
            ){
                LogInScreen(navController = navController)
            }
        }

ここで、注意する点はNavHostで作成するnavgraphの関係です。
navigationでは、navgraphにおいてRouteを作成するので、呼び出しもとのNavHostに、どんなRouteが定義されたかを教える必要があり、NavHostで、route = route名を定義することに注意が必要です。

image.png
参考にした記事

また、上記のコードでは意味のある区分分けを行ってもコードのまとまりがわかりにくいので、NavGraphBuilderを拡張させNavHost内で呼び出します。

fun NavGraphBuilder.authenticateNav(
    navController: NavHostController
){
    navigation(
        startDestination = Screen.LogInScreen.route,
        route = AUTHENTICATE_ROUTE,
    ){
        composable(
            route = Screen.LogInScreen.route
        ){
            LogInScreen(navController = navController)
        }
    }
}

これを同様に、HomeScreen, DetailScreenでも行うとNavHostは以下のように非常にコンパクトになります。

@Composable
fun NavigationSetUp(
    navController: NavHostController
){
    NavHost(
        navController = navController,
        startDestination = AUTHENTICATE_ROUTE,
        route = ROOT_ROUTE
    ){
        homeScreenNav(navController = navController)
        authenticateNav(navController = navController)
    }
}

以上のサンプルコードを実行すると、以下のようになります。

navigation2 (1).gif

##3. まとめ
こちらも併せて読んでいただくと、Navigationの実装が一通りわかると思います。
管理する画面構成が多い時ほど、意味のある区分分けを行って、画面遷移を行うことの大切さを知れました。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?