BottomNavigation: mi ez, felépítése és beállítása Jetpack Compose-ban

Szerző: IT Sectr Megjelenés: 2026-06-29 Olvasási idő: 8 perc

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 — alsó navigációs panel 3–5 képernyőhöz, NavigationBar segítségével Material3-ban implementálva
  • NavigationBarItem — a panel eleme ikonnal, címkével és jelvénnyel az értesítésekhez
  • Kapcsolat a NavHost-tal — az elem kiválasztása elindítja a navigate() függvényt a NavController-ben a gráf váltásához
  • Material3 Dynamic Color-t és a rendszernavigáció automatikus figyelembevételét adja hozzá a WindowInsets segítségével
  • Badge — értesítési jelvény az ikonon, BadgedBox segítségével megvalósítva számmal

Mi az a BottomNavigation Jetpack Compose-ban?

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.

kotlin
@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éterTípusLeírás
icon@Composable () -> UnitA panel elem ikonja
label@Composable (() -> Unit)?Szöveges címke az ikon alatt
selectedBooleanA kiválasztott elem jelzője
onClick() -> UnitVisszahívás megnyomáskor
badge@Composable (() -> Unit)?Jelvény az értesítések számával

BottomNavigation csatlakoztatása NavHost-hoz

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.

kotlin
@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.

NavigationBar Material3-ban: Dynamic Color és adaptáció

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.

NavigationBar színeinek testreszabása

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.

Értesítési jelvények és számlálók az elemeken

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).

kotlin
@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

Hány elemnek kell lennie a BottomNavigation-ben?

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.

Hogyan lehet elrejteni a BottomNavigation-t a gyermek képernyőkön?

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.

Mi a különbség a NavigationBar (M3) és a BottomNavigation (M2) között?

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.

Miért jön létre újra a képernyő a BottomNavigation elem megnyomásakor?

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.

Hogyan lehet testreszabni a lapok közötti váltás animációját?

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

  • BottomNavigation (NavigationBar M3-ban) — alsó panel az alkalmazás 3–5 fő képernyője közötti váltáshoz
  • NavigationBarItem — a panel eleme ikonnal, címkével, jelvénnyel és kiválasztási állapottal
  • Integráció a NavController-rel popUpTo, launchSingleTop és restoreState paramétereket igényel a verem helyes kezeléséhez
  • Material3 NavigationBar támogatja a Dynamic Color-t, a BadgedBox-ot, a WindowInsets-t és az aktív elem animációját
  • BadgedBox — komponens az értesítési jelvényekhez számmal vagy ponttal az elem ikonján
  • A kiválasztás állapota a currentBackStackEntryAsState-ből kerül kiszámításra a NavController-rel való szinkronizáláshoz
  • A panel gyermek képernyőkön való elrejtéséhez használjon feltételes megjelenítést a Scaffold bottomBar-ban az útvonalak listája alapján

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.

Projekt megbeszélése

Olvassa el is