
みなさまこんにちは〜!
メモリアインクのすだです。
本日は、
KotlinのNavigation ComposeとBottomNavigationを使って
複数の画面を切り替える方法について解説していきます!
この記事を読んでわかること…
・Navigation ComposeとBottomNavigationを使って画面下部にナビゲーションバーを実装する方法
Navigation Composeに関しては以下の記事でまとめています。
ぜひ併せてご覧ください。
-300x158.png)
-300x158.png)
環境
- Kotlin (ver 1.9.0)
- Android Studio (Giraffe | 2022.3.1 Patch 3)
BottomNavigationとは?
BottomNavigation
は Jetpack Compose に標準で用意されている UI コンポーネントのひとつで、
「画面の下にナビゲーションバー(タブ)を配置するためのパーツ」です。
公式では androidx.compose.material.BottomNavigation
として提供されています。
基本的には、
Scaffold(
bottomBar = {
BottomNavigation {
// 各タブのアイテムを配置
}
}
) {
// 中身(NavHostなど)
}
上記のように構成します。
Scaffold
で画面全体の骨組みを作り、その中で bottomBar
に BottomNavigation
を設置するのがComposeの基本スタイルです。
イメージとしては以下の図のような画面です。
+---------------------------+
| 画面コンテンツ |
| |
| |
| |
+---------------------------+
| ホーム | 登録 | 設定 | メニュー | ← これが BottomNavigation
+---------------------------+
BottomNavigationとの連携方法
BottomNavigationを使うには、Navigation ComposのNavControllerと連携して画面ごとのルートに遷移させるようにします。
基本構成は以下です:
BottomNavigationItem
をループで表示navController.navigate(route)
で画面遷移NavHost
と現在の画面を紐付け
今回は例として
・画面下にタブ(BottomNavigation)を設置し、
・「ホーム画面」と「設定画面」を切り替えられるようにする
・さらには、タブの選択状態や画面遷移の状態も適切に管理する
という実装を行います。
まずは全体のコードから▼
sealed class Screen(val route: String, val label: String, val icon: ImageVector) {
object Home : Screen("home", "ホーム", Icons.Default.Home)
object Settings : Screen("settings", "設定", Icons.Default.Settings)
}
val bottomScreens = listOf(
Screen.Home,
Screen.Settings
)
@Composable
fun MainScreen() {
val navController = rememberNavController()
Scaffold(
bottomBar = {
BottomNavigation {
val currentRoute = navController.currentBackStackEntryAsState().value?.destination?.route
bottomScreens.forEach { screen ->
BottomNavigationItem(
icon = { Icon(screen.icon, contentDescription = screen.label) },
label = { Text(screen.label) },
selected = currentRoute == screen.route,
onClick = {
if (currentRoute != screen.route) {
navController.navigate(screen.route) {
popUpTo(navController.graph.startDestinationId) { saveState = true }
launchSingleTop = true
restoreState = true
}
}
}
)
}
}
}
) { innerPadding ->
NavHost(
navController = navController,
startDestination = Screen.Home.route,
modifier = Modifier.padding(innerPadding)
) {
composable(Screen.Home.route) { HomeScreen() }
composable(Screen.Settings.route) { SettingsScreen() }
}
}
}
@Composable
fun HomeScreen() {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text("ホーム画面")
}
}
@Composable
fun SettingsScreen() {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text("設定画面")
}
}
少しずつ区切って解説していきます。
① sealed class Screen(画面の定義)
sealed class Screen(val route: String, val label: String, val icon: ImageVector) {
object Home : Screen("home", "ホーム", Icons.Default.Home)
object Settings : Screen("settings", "設定", Icons.Default.Settings)
}
画面ごとのルート名("home"
など)・表示名・アイコンをまとめて定義。sealed class
を使うことで、BottomBarの画面一覧をタイプセーフに管理できます。
② Scaffold(ボトムバーを一括管理)
Scaffold(
bottomBar = {
Scaffold
は トップバーやボトムバーなどを一括管理する便利なレイアウトコンポーネントです。
画面本体(NavHost
など)が「バーの下に隠れないようにする」ために、余白(padding)を自動で計算してくれます。
Composeでは、NavHost
自体が UI上に表示される領域(画面本体)を担うため、
Scaffold(
topBar = { TopAppBar(...) },
bottomBar = { BottomNavigation(...) }
) { innerPadding ->
NavHost(..., modifier = Modifier.padding(innerPadding))
}
このようにinnerPadding
をセットしてBottomNavigation
(下部バー)と中身が重なるのを防ぎます。
③ bottomScreens(ボトムバーに表示する画面リスト)
val bottomScreens = listOf(
Screen.Home,
Screen.Settings
)
ここに定義した画面だけが BottomNavigation に表示されます。
④ MainScreen() の構成(UI全体)
@Composable
fun MainScreen() {
val navController = rememberNavController()
画面構成のメインとなる Composableです。NavController
を使って画面遷移を管理します。
⑤ BottomNavigation(下部タブUI)
BottomNavigation {
val currentRoute = navController.currentBackStackEntryAsState().value?.destination?.route
navController. ~
で現在表示中の画面のルート(文字列)を取得します。
これで「どの画面が表示中か?」を判断してタブの選択状態を制御します。
⑥ BottomNavigationItem(タブの各項目)
bottomScreens.forEach { screen ->
BottomNavigationItem(
icon = { Icon(screen.icon, contentDescription = screen.label) },
label = { Text(screen.label) },
selected = currentRoute == screen.route,
onClick = {
if (currentRoute != screen.route) {
navController.navigate(screen.route) {
popUpTo(navController.graph.startDestinationId) { saveState = true }
launchSingleTop = true
restoreState = true
}
}
}
)
}
先ほど定義したbottomScreensをループし、BottomNavigationItem
を使って各項目を表示させます。
各パラメータは以下を意味しています。
・icon
:アイコン表示(Icons.Default.Home
など)
・label
:テキスト表示
・selected
:選択中かどうか
・onClick
:タップ時の画面遷移処理
まとめ
おつかれさまでした。いかがでしたでしょうか!
Navigation ComposeとBottomNavigationを組み合わせれば、タブUIをComposeだけでスッキリと実装できます。
画面遷移はNavControllerに任せる、
画面表示はNavHostで管理、
そしてUIの下部はBottomNavigationで実装 といったイメージで実践してみてください!



技術者としてのキャリアパスを次のレベルへと進めたい皆様、
未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】
自分の市場価値をさらに向上させてみませんか?
それではまた次の記事でお会いしましょう!
コメント