#目次
- Navigation Arguments, Nested Navigationとは
- サンプルコード
- まとめ
##1. Navigation Arguments, Nested Navigationとは
Navigation Arguments
‥画面遷移時に、画面間で共有できる値。この値は、{ } (プレースホルダ)を用い、argumentsを型を指定してlistで管理できます。また、SavedStateHandleを使って、画面遷移時に必要なargumentsを取得できますが、今回は説明を省きます。
以下の実装を行います(UIの詳細については説明を省きます。)
Nested Navigation
‥デスティネーションを、モジュール化すること。NavigationHost以下に、NavGraph
を作成することで、Navigation間の依存関係を切り離す役割を持っています。(NavHost
で、呼び出すcomposableをさらにグループで分けることで実装を行います。)
以下の実装を行います(UIの詳細については説明を省きます。)
##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
‥このコンポーザブルを呼び出しているNavHost
のcomposable
を確認すると、routeを**{ itemId }というプレースホルダ**とともに取り扱っていることがわかります。そして、arguments内で、argumentsのタイプを決定することができ、StringType
としてることがわかります。
注意点として、HomeScreen
でオブジェクトを指定して画面を遷移する際に、**/**の記述がないと正しく遷移が行われないので注意が必要です。
navController.navigate(route = Screen.DetailScreen.route + "/1")
以上のコードを実行すると、以下のようにできます。
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名を定義することに注意が必要です。
また、上記のコードでは意味のある区分分けを行ってもコードのまとまりがわかりにくいので、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)
}
}
以上のサンプルコードを実行すると、以下のようになります。
##3. まとめ
こちらも併せて読んでいただくと、Navigationの実装が一通りわかると思います。
管理する画面構成が多い時ほど、意味のある区分分けを行って、画面遷移を行うことの大切さを知れました。