BottomNavigation (NavigationBar Material3-ban) egy Material Design komponens, amely navigációt biztosít az alkalmazás három-öt fő képernyője között. Jetpack Compose-ban az alsó panel a NavigationBar vagy BottomNavigation segítségével van implementálva, ahol minden elemet egy ikon és egy szöveges címke képvisel. A Google Material Design (2025) szerint a BottomNavigation iOS és Android számára ajánlott elsődleges navigációs mintaként. A panel automatikusan alkalmazkodik a rendszernavigáció (Gesture Navigation) magasságához a WindowInsets segítségével. A NavigationBar Material3-ban támogatja a dynamic color, badge és adaptív margókat.
Főbb pontok
BottomNavigation egy Material Design komponens az alsó navigációs panelhez, amely három-öt menüpontot jelenít meg. Jetpack Compose-ban a BottomNavigation (Material2) és NavigationBar (Material3) composable függvényeken keresztül van implementálva. A panel a képernyő alján helyezkedik el, és gyors hozzáférést biztosít az alkalmazás kulcsfontosságú szakaszaihoz.
A BottomNavigation fő feladata az elsődleges navigáció megszervezése a képernyőszintek között. A panel minden eleme egy külön képernyőt képvisel (Home, Search, Profile). Megnyomásával a tartalom a képernyő fő területén változik. A BottomNavigation nem beágyazott navigációra szolgál — ehhez lapokat (Tabs) használunk a felső részben.
A Material Design Guidelines (2025) szerint az alsó panel csak azokat a szakaszokat tartalmazhatja, amelyek az alkalmazás bármely pontjáról elérhetők. A panel elrejtése a gyermek képernyőkön (pl. részletes oldal megnyitásakor) általános gyakorlat. Compose-ban a BottomNavigation láthatóságát a Scaffold állapota vagy a NavController aktuális útvonalán alapuló feltételes megjelenítés kezeli.
Material3-ban ajánlott a NavigationBar használata a Legacy BottomNavigation helyett. A NavigationBar tartalmazza a Dynamic Color-t, a WindowInsets támogatást és a továbbfejlesztett lenyomási animációt. A Google szerint a NavigationBar egy jövőbe mutató komponens, míg a M2-ből származó BottomNavigation csak visszafelé kompatibilitás céljából marad meg.
A NavigationBar minden eleme a NavigationBarItem composable segítségével van implementálva. Az elem paraméterei: icon (ikon), label (szöveges címke), selected (kiválasztás állapota) és onClick (visszahívás). A NavigationBarItem automatikusan alkalmazza a kiválasztott színt (primary) és az ikon méretváltozásának animációját aktiváláskor.
@Composable
fun BottomNavBar() {
val items = listOf(
Screen.Home,
Screen.Search,
Screen.Profile
)
var selectedItem by remember { mutableIntStateOf(0) }
NavigationBar {
items.forEachIndexed { index, item ->
NavigationBarItem(
icon = { Icon(item.icon, contentDescription = item.label) },
label = { Text(item.label) },
selected = selectedItem == index,
onClick = { selectedItem = index }
)
}
}
}
A NavigationBarItem ikonjainak Filled állapotúnak kell lenniük a kiválasztott állapothoz és Outlined állapotúnak a nem kiválasztott állapothoz. A Material Icons mindkét készletet biztosítja: Icons.Filled.Home és Icons.Outlined.Home. Alapértelmezés szerint a NavigationBarItem a filled változatot jeleníti meg selected esetén. Ha eltérő megjelenítésre van szükség, feltételesen adja át az ikont: if (selected) Filled.X else Outlined.X.
Az elem szöveges címkéjének hossza — legfeljebb 12 karakter (latin ábécé) vagy 8 karakter (cirill). A hosszú címkék három ponttal vannak lerövidítve. A címkékhez használja a maxLines = 1 és ellipsis = TextTruncation.Ellipsis beállításokat. Ha a címkének mindig láthatónak kell lennie, állítsa be az alwaysShowLabel = true paramétert (alapértelmezés true).
| Paraméter | Típus | Leírás |
|---|---|---|
| icon | @Composable () -> Unit | A panel elem ikonja |
| label | @Composable (() -> Unit)? | Szöveges címke az ikon alatt |
| selected | Boolean | A kiválasztott elem jelzője |
| onClick | () -> Unit | Visszahívás megnyomáskor |
| badge | @Composable (() -> Unit)? | Jelvény az értesítések számával |
A selectedItem közvetlen frissítése nem irányítja át a navigációt — a képernyők váltásához integráció szükséges a NavController-rel. A tipikus minta: az onClick a NavigationBarItem-ben meghívja a navController.navigate(route) függvényt, és a selectedItem a NavController aktuális útvonalából kerül meghatározásra.
A NavController tárolja az aktuális back stack-et. Annak meghatározásához, hogy a panel melyik eleme van kiválasztva, hasonlítsa össze az aktuális útvonalat (navController.currentBackStackEntryAsState().value?.destination?.route) az elemek útvonalaival. Ha az útvonal egyezik — az elem kiválasztottnak minősül. Ez kiküszöböli az állapot duplikációját.
@Composable
fun MainScreen(navController: NavController) {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
Scaffold(
bottomBar = {
NavigationBar {
items.forEach { item ->
NavigationBarItem(
icon = { Icon(item.icon, contentDescription = item.label) },
label = { Text(item.label) },
selected = currentRoute == item.route,
onClick = {
navController.navigate(item.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
) { /* content */ }
}
Kulcsfontosságú beállítások a navigate()-ben: a popUpTo(startDestination) megakadályozza a back stack felhalmozódását a lapok váltásakor, a launchSingleTop kizárja az útvonal duplikációját a veremben, a restoreState pedig visszaállítja a lap előző látogatásának állapotát. E paraméterek nélkül minden egyes megnyomás új bejegyzést hoz létre a veremben, ami a Vissza gomb helytelen működéséhez vezet.
A Material3 (M3) NavigationBar-t és NavigationBarItem-t biztosít a Material2-ből származó BottomNavigation helyettesítéseként. Az M3 fő előnyei: Dynamic Color, adaptív magasság, ripple animáció az elem teljes szélességében és WindowInsets támogatás a rendszernavigáció figyelembevételéhez.
A Dynamic Color automatikusan kiválasztja a NavigationBar színeit a készülék háttérkép alapján (Android 12+). Az aktív elem primary színűre, az inaktívak onSurfaceVariant színűre színeződnek. Alapértelmezés szerint a NavigationBar a Modifier.navigationBarsPadding() segítségével a rendszernavigáció fölé emelkedik. Kézi vezérléshez használja a windowInsets paramétert.
A NavigationBar M3-ban automatikusan animálja az aktív elem szélességét — az ikon balra mozog, a címke pedig kiterjed. Az animáció 300 ms-ig tart, és a szabványos Compose easing-et használja. Ha ez a viselkedés nem kívánatos, állítsa be a címke állandó láthatóságát a alwaysShowLabel = true segítségével a NavigationBarItem-ben.
A színek felülírásához adja át a NavigationBarColors-t a colors paraméterben. Alapértelmezés szerint a NavigationBarDefaults.colors() van használatban, de saját színeket is beállíthat: containerColor (panel háttér), contentColor (ikonok színe), indicatorColor (aktív elem háttere). Ellentétben az M2-vel, ahol a színek a BottomNavigationDefaults segítségével voltak beállítva, az M3-ban az egységes NavColors felület használatos.
Ha a projektben M2-ből (androidx.compose.material) származó BottomNavigation van használatban, a Google az M3 NavigationBar-ra való migrálást javasolja. A migráció magában foglalja az importok cseréjét, a paraméterek frissítését és a @OptIn(ExperimentalMaterial3Api::class) hozzáadását. Az M2-ből származó BottomNavigation elavultnak minősül, és nem kap új funkciókat.
A NavigationBar állapota tárolja az aktuálisan kiválasztott elem indexét. Egyszerű esetekben a remember { mutableIntStateOf(0) } használatos. Az éles alkalmazásoknál azonban az indexet szinkronizálni kell a navigációs gráffal, nem lehet pusztán lokális UI állapot.
Az állapotkezelés főbb megközelítései: NavController-based (ajánlott) és ViewModel-based. Az első esetben a selectedItem a NavController aktuális útvonalából kerül kiszámításra. A második esetben — a ViewModel tárolja az aktuális képernyőt, és a NavigationBarItem beolvassa a StateFlow-t a ViewModel-ből. A NavController-based egyszerűbb, a ViewModel-based nagyobb kontrollt biztosít összetett logika esetén (hitelesítés, A/B tesztek).
A saveState és restoreState használatakor a NavController automatikusan menti és visszaállítja a LazyColumn és más komponensek állapotát minden lapon belül. Ez kiküszöböli a ViewModel szükségességét a görgetési pozíció tárolásához. A mentés azonban nem alkalmazható a beviteli mezőkre — azokhoz SavedStateHandle vagy ViewModel szükséges.
Badge egy kompakt értesítési jelző, amely a NavigationBarItem ikonján jelenik meg. Material3-ban a jelvény a BadgedBox segítségével van implementálva, amely körülveszi az ikont, és a jelvényt a jobb felső sarokba helyezi. A Badge tartalmazhat számot (értesítések száma) vagy pontot (egyszerű jelenléti jelzés).
@Composable
fun HomeItem(unreadCount: Int) {
NavigationBarItem(
icon = {
BadgedBox(badge = {
if (unreadCount > 0) {
Badge { Text(unreadCount.toString()) }
}
}) {
Icon(Icons.Filled.Home, contentDescription = "Kezdőlap")
}
},
label = { Text("Home") },
selected = false,
onClick = { }
)
}
A BadgedBox automatikusan a Badge-t a gyermekelem jobb felső sarkába pozícionálja. Ha a szám meghaladja a 99-et, a Badge „99+“ jelenít meg. A jelvény elrejtéséhez nulla érték esetén használja az if (count > 0) feltételt. A Material3-ból származó Badge alapértelmezés szerint error (piros) színű fehér szöveggel. Testreszabás a BadgeDefaults.colors(containerColor, contentColor) segítségével.
Material2-ben a jelvény nem létezett — kézzel kellett megrajzolni Canvas segítségével vagy harmadik féltől származó könyvtárakat használni. A Material3 ezt a problémát egy natív komponenssel oldotta meg. Az Android Developers (2025) szerint a BadgedBox a NavigationBar-t használó alkalmazások 40%-ában van jelen, amelynek 60%-a olvasatlan üzenetek megjelenítésére szolgál.
Gyakran Ismételt Kérdések
A Material Design 3-tól 5 elemig javasol. Kevesebb mint három — nem célszerű (jobb Tabs-okat használni). Több mint öt — rontja a címkék olvashatóságát és csökkenti a touch-target-et. Ha több mint 5 szakaszra van szükség, használjon Navigation Rail-t (táblagépek) vagy Drawer-t.
Határozza meg az útvonalak listáját, ahol a panel látható (általában gyökér útvonalak). A Scaffold bottomBar-ban csak akkor adja át a NavigationBar-t, ha a currentRoute a bottomNavRoutes-ban van. Alternatíva — NavHost külön gráffal a beágyazott képernyők számára bottomBar nélkül.
A Material3-ból származó NavigationBar támogatja a Dynamic Color-t, a BadgedBox-ot, a WindowInsets-t és az aktív elem animált szélességét. A Material2-ből származó BottomNavigation egy régi API e funkciók nélkül. A Google a NavigationBar használatát javasolja új projektekhez és a meglévők migrálását.
A probléma a saveState és restoreState hiánya a navigate()-ben. Nélkülük a NavController nem menti az előző lap állapotát. Adja hozzá a popUpTo(startDestination) { saveState = true } és restoreState = true paramétereket a NavOptions-ban a LazyColumn, a görgetés és a beviteli mezők megőrzéséhez.
A váltási animáció a NavHost szintjén van szabályozva, nem a BottomNavigation szintjén. Adjon hozzá composable(route, enterTransition, exitTransition) elemet egyedi animációkkal. A BottomNavigation esetében a tipikus fading animáció (fadeIn + fadeOut) 300 ms időtartammal.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is