#目次
- Navigationとは
- サンプルコード
- まとめ
##1. Navigationとは
この記事は、Jetpack Compose Scaffold(BottomNavigation UI)で構築したUIをもとに、Navigationを実装するので、UIの説明は省略させていただきます。
NavHost
‥rememberNavControllerを渡し、NavControllerのサブクラスであるNavHostControllerでステートを管理します。
また、NavGraphBuilder
を用いて、navgraphに対し画面遷移情報を追加します。
#####ここで、NavGraphBuilder
に、どのようにnavgraphをついかするの??
composableにおいて、routeを渡すことでnavgraphを構成することができます。では、詳細を以下のコードでみてみましょう。
public fun NavGraphBuilder.composable(
route: String,
arguments: List<NamedNavArgument> = emptyList(),
deepLinks: List<NavDeepLink> = emptyList(),
content: @Composable (NavBackStackEntry) -> Unit
) {
addDestination(
ComposeNavigator.Destination(provider[ComposeNavigator::class], content).apply {
this.route = route
arguments.forEach { (argumentName, argument) ->
addArgument(argumentName, argument)
}
deepLinks.forEach { deepLink ->
addDeepLink(deepLink)
}
}
)
}
引数のrouteに注目し、addDestination以下にthis.route = routeとあり、渡したrouteをもとに画面遷移の情報を追加していることがわかります。
また、content
スロットがあるので、コンポーザブルをラムダで呼び出すことができます。その他の引数についての説明は別記事で説明します。
では、どのタイミングでrouteを渡すかというと、以下のようになります。
ここで、sealed class にしている意図として網羅性を担保できることです。
それでは、サンプルコードを用いて実際に画面遷移を行っていきます。
##2. サンプルコード
navgraph
を作成する。
@Composable
fun ScreenNavigation(
navController: NavHostController
){
NavHost(
navController = navController,
startDestination = Screen.MailScreen.route
){
composable(Screen.MailScreen.route){
MailScreen()
}
composable(Screen.ProfileScreen.route){
ProfileScreen()
}
}
}
NavHostのスロットで、composableは上記のように呼び出します。
次に、Scaffold
のスロットbottomBarで、BottomAppBar
を呼び出し、**Scaffoldのcontent(スロット)**で、上記のScreenNavigation
を呼び出します。
Scaffoldは、マテリアルコンポーネントを対応する画面上に配置することができます。よって、bottomBarで呼び出しているBottomAppBar
のcontent(スロット)で以下のコンポーザブルを呼び出します。
@Composable
fun CustomBottomNav(
navController: NavHostController
) {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
BottomNavigation(
modifier = Modifier
.padding(0.dp, 0.dp, 0.dp, 5.dp)
.height(100.dp),
elevation = 0.dp
) {
screenItem.forEach { screen ->
BottomItem(
screen = screen,
currentDestination = currentDestination,
navController = navController
)
}
}
}
ここで重要になってくるのは、navgraphで作成した画面遷移がどのように実行されるかを考えることです。
NavHost
は、画面遷移を行うためにBackStackを生成します。このBackStackというリストを利用することで、NavHost
が再コンポーズされるたびにcomposableで記述したコンポーザブルを呼び出して画面を更新しています。
よって、現状の画面がどのコンポーザブルで構成されているかをBottomNavigationに伝える必要があるので、上記のnavBackStackEntry
をステートとして管理し、currentDestination
で、BackStackから更新される画面を受け取ることができます。
最後に、BottonNavigation
のスロットで呼び出されている。BottomItem
について確認していきます。
@Composable
fun RowScope.BottomItem(
screen: Screen,
currentDestination: NavDestination?,
navController: NavHostController
){
BottomNavigationItem(
icon = {
Icon(
imageVector = screen.icon,
contentDescription = ""
)
},
selected = currentDestination?.hierarchy?.any {
it.route == screen.route
} == true,
unselectedContentColor = LocalContentColor.current.copy(alpha = ContentAlpha.disabled),
onClick = {
navController.navigate(screen.route)
}
)
}
BottonNavigation
内で、コンポーザブルを呼び出すために、上記のコンポーザブルはRowScopeのコンポーザブルとして定義し、スロットで、BottomNavigationItem
を呼び出します。
BottomNavigationItem
では、icon, label, selected
などBottomNavigationを構成する要素を細かく設定することができます。ここでは、BottomNavigationに関連する処理だけを説明します。
selected
‥any{}は、与えられたリストが条件を満たせばBooleanで結果を返してくれるものです。ここで何を確認しているのかというと、BackStack
(リスト)から与えられたrouteと、画面を構成してるrouteがマッチしているかを確認しています。
上記のコードを実行すると、
このように実装することができます。
##3. まとめ
今回は、Scaffoldを用いてBottonNavigationを実装してみました。
画面遷移時の、Argumentsの画面間受け渡し、Nested Navigationを今後改めて説明していきたいと思います。