はじめに
引き続きNavigation3での遷移実装を紹介していきます。
今回はボトムナビゲーションです
コード
@Serializable
object Home : NavKey
@Serializable
object Profile : NavKey
@Serializable
object Settings : NavKey
@Serializable
data class Detail(
val userInfo: UserInfo
) : NavKey
// ボトムナビゲーションのアイテムを定義
sealed class BottomNavItem(
val route: NavKey,
val title: String,
val icon: ImageVector
) {
data object Home : BottomNavItem(
route = com.example.compose3sample.Home,
title = "ホーム",
icon = Icons.Default.Home
)
data object Profile : BottomNavItem(
route = com.example.compose3sample.Profile,
title = "プロフィール",
icon = Icons.Default.Person
)
data object Settings : BottomNavItem(
route = com.example.compose3sample.Settings,
title = "設定",
icon = Icons.Default.Settings
)
}
class MainActivity : ComponentActivity() {
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
Compose3SampleTheme {
AppNavigation3WithBottomBar()
}
}
}
}
@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
@Composable
fun AppNavigation3WithBottomBar(modifier: Modifier = Modifier) {
// Navigation3のバックスタックを作成
val backStack = rememberNavBackStack(Home)
// ボトムナビゲーションのアイテムリスト
val bottomNavItems = listOf(
BottomNavItem.Home,
BottomNavItem.Profile,
BottomNavItem.Settings
)
// 現在のルートを取得
val currentRoute = backStack.lastOrNull()?.let { entry ->
when (entry) {
is Home -> Home as NavKey
is Profile -> Profile as NavKey
is Settings -> Settings as NavKey
else -> Home as NavKey
}
} ?: (Home as NavKey)
Scaffold(
modifier = modifier.fillMaxSize(),
bottomBar = {
NavigationBar {
bottomNavItems.forEach { item ->
NavigationBarItem(
icon = { Icon(item.icon, contentDescription = item.title) },
label = { Text(item.title) },
selected = currentRoute == item.route,
onClick = {
// 現在のルートと異なる場合のみナビゲート
if (currentRoute != item.route) {
// バックスタックをクリアして新しいルートに移動
while (backStack.size > 1) {
backStack.removeLast()
}
if (backStack.lastOrNull() != item.route) {
backStack.removeLast()
backStack.add(item.route)
}
}
}
)
}
}
}
) { innerPadding ->
// NavDisplayを使用してナビゲーションを実装
NavDisplay(
backStack = backStack,
entryProvider = entryProvider {
entry<Home> {
HomeScreen(
onNavigateToDetail = { userInfo ->
backStack.add(Detail(userInfo = userInfo))
},
modifier = Modifier.padding(innerPadding)
)
}
entry<Profile> {
ProfileScreen(
modifier = Modifier.padding(innerPadding)
)
}
entry<Settings> {
SettingsScreen(
modifier = Modifier.padding(innerPadding)
)
}
entry<Detail> { detail ->
DetailScreen(
userInfo = detail.userInfo,
onNavigateBack = { backStack.removeLast() },
modifier = Modifier.padding(innerPadding)
)
}
}
)
}
}
@Composable
fun HomeScreen(
onNavigateToDetail: (UserInfo) -> Unit,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "Hello Android! (Navigation3)",
modifier = Modifier.padding(bottom = 16.dp)
)
Button(
onClick = {
val userInfo = UserInfo(
id = 123,
name = "山田太郎",
email = "yamada@example.com",
age = 25
)
onNavigateToDetail(userInfo)
}
) {
Text("詳細画面へ")
}
}
}
@Composable
fun ProfileScreen(
modifier: Modifier = Modifier
) {
Column(
modifier = modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "プロフィール画面",
modifier = Modifier.padding(bottom = 16.dp)
)
Text(
text = "ユーザー情報を表示します",
modifier = Modifier.padding(bottom = 8.dp)
)
}
}
@Composable
fun SettingsScreen(
modifier: Modifier = Modifier
) {
Column(
modifier = modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "設定画面",
modifier = Modifier.padding(bottom = 16.dp)
)
Text(
text = "アプリの設定を変更できます",
modifier = Modifier.padding(bottom = 8.dp)
)
}
}
@Composable
fun DetailScreen(
userInfo: UserInfo,
onNavigateBack: () -> Unit,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "詳細画面です (Navigation3)",
modifier = Modifier.padding(bottom = 16.dp)
)
Text(
text = "ID: ${userInfo.id}",
modifier = Modifier.padding(bottom = 8.dp)
)
Text(
text = "名前: ${userInfo.name}",
modifier = Modifier.padding(bottom = 8.dp)
)
Text(
text = "メール: ${userInfo.email}",
modifier = Modifier.padding(bottom = 8.dp)
)
Text(
text = "年齢: ${userInfo.age}歳",
modifier = Modifier.padding(bottom = 16.dp)
)
Button(
onClick = onNavigateBack
) {
Text("戻る")
}
}
}
最後に
従来のComposeNavigationと大差はないので直感的に実装しやすいですね