BottomNavigation: ano ito, istraktura at pag-setup sa Jetpack Compose

May-akda: IT Sectr Nai-publish: 2026-06-29 Oras ng pagbabasa: 8 min

BottomNavigation (NavigationBar sa Material3) ay isang Material Design component na nagbibigay ng navigasyon sa pagitan ng tatlo hanggang limang pangunahing screen ng application. Sa Jetpack Compose, ang ibabang panel ay ipinapatupad sa pamamagitan ng NavigationBar o BottomNavigation, kung saan ang bawat elemento ay kinakatawan ng isang icon at text label. Ayon sa Google Material Design (2025), ang BottomNavigation ay inirerekomenda para sa iOS at Android bilang pangunahing pattern ng primaryang navigasyon. Ang panel ay awtomatikong umaangkop sa taas ng system navigation (Gesture Navigation) sa pamamagitan ng WindowInsets. Ang NavigationBar sa Material3 ay sumusuporta sa dynamic color, badge at adaptive na mga margin.

Mga pangunahing punto

  • BottomNavigation — ibabang panel ng navigasyon para sa 3–5 screen, na ipinapatupad sa pamamagitan ng NavigationBar sa Material3
  • NavigationBarItem — elemento ng panel na naglalaman ng icon, label at badge para sa mga notification
  • Koneksyon sa NavHost — ang pagpili ng elemento ay nagti-trigger ng navigate() sa NavController para sa paglipat ng graph
  • Material3 ay nagdaragdag ng Dynamic Color at awtomatikong pagsasaalang-alang ng system navigation sa pamamagitan ng WindowInsets
  • Badge — badge ng notification sa icon, na ipinapatupad sa pamamagitan ng BadgedBox na may bilang

Ano ang BottomNavigation sa Jetpack Compose?

BottomNavigation ay isang Material Design component para sa ibabang panel ng navigasyon na nagpapakita ng tatlo hanggang limang item ng menu. Sa Jetpack Compose, ito ay ipinapatupad sa pamamagitan ng composable function na BottomNavigation (Material2) at NavigationBar (Material3). Ang panel ay inilalagay sa ibabang bahagi ng screen at nagbibigay ng mabilis na access sa mga pangunahing seksyon ng application.

Ang pangunahing gawain ng BottomNavigation ay ang pag-oorganisa ng primaryang navigasyon sa pagitan ng mga antas ng screen. Ang bawat elemento ng panel ay kumakatawan sa isang hiwalay na screen (Home, Search, Profile). Ang pagpindot ay nagpapalit ng nilalaman sa pangunahing lugar ng screen. Ang BottomNavigation ay hindi nilayon para sa nested navigasyon — para dito, ginagamit ang mga tab (Tabs) sa itaas na bahagi.

Ayon sa Material Design Guidelines (2025), ang ibabang panel ay dapat lamang maglaman ng mga seksyon na naa-access mula sa anumang punto ng application. Ang pagtatago ng panel sa mga child screen (halimbawa, kapag nagbubukas ng pahina ng detalye) ay isang karaniwang kasanayan. Sa Compose, ang visibility ng BottomNavigation ay pinamamahalaan sa pamamagitan ng estado ng Scaffold o conditional rendering batay sa kasalukuyang ruta ng NavController.

Sa Material3, inirerekomenda na gamitin ang NavigationBar sa halip na Legacy BottomNavigation. Ang NavigationBar ay may kasamang Dynamic Color, suporta para sa WindowInsets at pinahusay na animation ng pagpindot. Ayon sa Google, ang NavigationBar ay isang prospektibong component, habang ang BottomNavigation mula sa M2 ay nananatili lamang para sa backward compatibility.

Ang bawat elemento ng NavigationBar ay ipinapatupad sa pamamagitan ng composable na NavigationBarItem. Ang mga parameter ng elemento: icon (icon), label (text label), selected (estado ng pagpili) at onClick (callback). Awtomatikong inilalapat ng NavigationBarItem ang napiling kulay (primary) at ang animation ng pagbabago ng laki ng icon sa pag-activate.

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

Ang mga icon para sa NavigationBarItem ay dapat na Filled para sa napiling estado at Outlined para sa hindi napiling estado. Ang Material Icons ay nagbibigay ng parehong set: Icons.Filled.Home at Icons.Outlined.Home. Bilang default, ang NavigationBarItem ay nagpapakita ng filled variant para sa selected. Kung kailangan ang ibang display, ibigay ang icon nang may kondisyon: if (selected) Filled.X else Outlined.X.

Ang haba ng text label ng elemento — hindi hihigit sa 12 character (Latin alphabet) o 8 character (Cyrillic). Ang mahahabang label ay pinuputol ng ellipsis. Para sa mga label, gamitin ang maxLines = 1 at ellipsis = TextTruncation.Ellipsis. Kung ang label ay palaging kinakailangan, itakda ang parameter na alwaysShowLabel = true (default true).

ParameterUriPaglalarawan
icon@Composable () -> UnitIcon ng elemento ng panel
label@Composable (() -> Unit)?Text label sa ilalim ng icon
selectedBooleanBandila ng napiling elemento
onClick() -> UnitCallback sa pagpindot
badge@Composable (() -> Unit)?Badge na may bilang ng mga notification

Pagkonekta ng BottomNavigation sa NavHost

Ang direktang pag-update ng selectedItem ay hindi nagre-redirect ng navigasyon — para sa paglipat ng mga screen, kailangan ang integrasyon sa NavController. Ang tipikal na pattern: ang onClick sa NavigationBarItem ay tumatawag sa navController.navigate(route), at ang selectedItem ay tinutukoy mula sa kasalukuyang ruta ng NavController.

Ang NavController ay nag-iimbak ng kasalukuyang back stack. Upang matukoy kung aling elemento ng panel ang napili, ihambing ang kasalukuyang ruta (navController.currentBackStackEntryAsState().value?.destination?.route) sa mga ruta ng mga elemento. Kung tumugma ang ruta — ang elemento ay itinuturing na napili. Tinatanggal nito ang pagdoble ng estado.

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 */ }
}

Mga pangunahing setting sa navigate(): ang popUpTo(startDestination) ay pumipigil sa pag-ipon ng back stack kapag nagpapalipat-lipat ng mga tab, ang launchSingleTop ay nag-aalis ng pagdoble ng ruta sa stack, at ang restoreState ay nagpapanumbalik ng estado ng nakaraang pagbisita sa tab. Kung wala ang mga parameter na ito, ang bawat pagpindot ay lumilikha ng bagong entry sa stack, na humahantong sa hindi tamang pag-uugali ng pindutan ng Bumalik.

NavigationBar sa Material3: Dynamic Color at adaptasyon

Ang Material3 (M3) ay nagbibigay ng NavigationBar at NavigationBarItem bilang kapalit ng BottomNavigation mula sa Material2. Mga pangunahing bentahe ng M3: Dynamic Color, adaptive na taas, ripple animation sa buong lapad ng elemento, at suporta para sa WindowInsets upang isaalang-alang ang system navigation.

Ang Dynamic Color ay awtomatikong pumipili ng mga kulay ng NavigationBar batay sa wallpaper ng device (Android 12+). Ang aktibong elemento ay kinukulayan ng primary, ang mga hindi aktibo — ng onSurfaceVariant. Bilang default, ang NavigationBar ay tumataas sa itaas ng system navigation sa pamamagitan ng Modifier.navigationBarsPadding(). Para sa manual na kontrol, gamitin ang parameter na windowInsets.

Ang NavigationBar sa M3 ay awtomatikong nag-a-animate ng lapad ng aktibong elemento — ang icon ay gumagalaw sa kaliwa at ang label ay lumalawak. Ang animation ay tumatagal ng 300 ms at gumagamit ng standard na Compose easing. Kung ang pag-uugali na ito ay hindi gusto, itakda ang label na palaging nakikita sa pamamagitan ng alwaysShowLabel = true sa NavigationBarItem.

Pag-customize ng mga kulay ng NavigationBar

Upang baguhin ang mga kulay, ibigay ang NavigationBarColors sa parameter na colors. Bilang default, ginagamit ang NavigationBarDefaults.colors(), ngunit maaari kang magtakda ng sarili mong mga kulay: containerColor (background ng panel), contentColor (kulay ng mga icon), indicatorColor (background ng aktibong elemento). Hindi tulad ng M2, kung saan ang mga kulay ay itinakda sa pamamagitan ng BottomNavigationDefaults, sa M3 ginagamit ang pinag-isang interface na NavColors.

Kung sa proyekto ay ginagamit ang BottomNavigation mula sa M2 (androidx.compose.material), inirerekomenda ng Google ang paglipat sa M3 NavigationBar. Kasama sa paglipat ang pagpapalit ng mga import, pag-update ng mga parameter, at pagdaragdag ng @OptIn(ExperimentalMaterial3Api::class). Ang BottomNavigation mula sa M2 ay itinuturing na luma at hindi tumatanggap ng mga bagong feature.

Ang estado ng NavigationBar ay nag-iimbak ng index ng kasalukuyang napiling elemento. Sa mga simpleng kaso, ginagamit ang remember { mutableIntStateOf(0) }. Gayunpaman, para sa mga production application, ang index ay dapat na naka-sync sa navigation graph, hindi lamang isang lokal na estado ng UI.

Mga pangunahing approach sa pamamahala ng estado: NavController-based (inirerekomenda) at ViewModel-based. Sa unang kaso, ang selectedItem ay kinakalkula mula sa kasalukuyang ruta ng NavController. Sa pangalawang kaso — ang ViewModel ay nag-iimbak ng kasalukuyang screen, at ang NavigationBarItem ay nagbabasa ng StateFlow mula sa ViewModel. Ang NavController-based ay mas simple, ang ViewModel-based ay nagbibigay ng higit na kontrol sa kumplikadong lohika (awtorisasyon, A/B test).

Kapag gumagamit ng saveState at restoreState, awtomatikong ini-save at ibinabalik ng NavController ang estado ng LazyColumn at iba pang mga component sa loob ng bawat tab. Tinatanggal nito ang pangangailangan para sa ViewModel upang iimbak ang scroll position. Gayunpaman, ang pag-save ay hindi naaangkop sa mga input field — nangangailangan sila ng SavedStateHandle o ViewModel.

Mga badge ng notification at counter sa mga elemento

Badge ay isang compact na indicator ng notification na ipinapakita sa icon ng NavigationBarItem. Sa Material3, ang badge ay ipinapatupad sa pamamagitan ng BadgedBox, na bumabalot sa icon at naglalagay ng badge sa kanang itaas na sulok. Ang Badge ay maaaring maglaman ng numero (bilang ng mga notification) o tuldok (simpleng indikasyon ng presensya).

kotlin
@Composable
fun HomeItem(unreadCount: Int) {
    NavigationBarItem(
        icon = {
            BadgedBox(badge = {
                if (unreadCount > 0) {
                    Badge { Text(unreadCount.toString()) }
                }
            }) {
                Icon(Icons.Filled.Home, contentDescription = "Tahanan")
            }
        },
        label = { Text("Home") },
        selected = false,
        onClick = { }
    )
}

Ang BadgedBox ay awtomatikong nagpo-position ng Badge sa kanang itaas na sulok ng child element. Kung ang numero ay lumampas sa 99, ang Badge ay nagpapakita ng “99+”. Upang itago ang badge sa zero na halaga, gamitin ang kondisyon na if (count > 0). Ang Badge mula sa Material3 ay may default na kulay na error (pula) na may puting text. Pag-customize sa pamamagitan ng BadgeDefaults.colors(containerColor, contentColor).

Sa Material2, ang badge ay wala — kailangan itong iguhit nang manu-mano sa pamamagitan ng Canvas o gumamit ng mga third-party na library. Nilutas ng Material3 ang problemang ito gamit ang isang native na component. Ayon sa Android Developers (2025), ang BadgedBox ay ginagamit sa 40% ng mga application na may NavigationBar, kung saan 60% ay para sa pagpapakita ng mga hindi pa nababasang mensahe.

Mga Madalas na Itanong

Ilang elemento ang dapat nasa BottomNavigation?

Inirerekomenda ng Material Design ang 3 hanggang 5 elemento. Mas mababa sa tatlo — hindi kapaki-pakinabang (mas mainam na gumamit ng Tabs). Higit sa lima — pinapahina ang pagiging madaling mabasa ng mga label at binabawasan ang touch-target. Kung kinakailangan ang higit sa 5 seksyon, gamitin ang Navigation Rail (mga tablet) o Drawer.

Paano itago ang BottomNavigation sa mga child screen?

Tukuyin ang listahan ng mga ruta kung saan nakikita ang panel (karaniwang mga root ruta). Sa Scaffold bottomBar, ibigay ang NavigationBar lamang kung ang currentRoute ay nasa bottomNavRoutes. Alternatibo — NavHost na may hiwalay na graph para sa mga nested screen na walang bottomBar.

Ano ang pagkakaiba sa pagitan ng NavigationBar (M3) at BottomNavigation (M2)?

Ang NavigationBar mula sa Material3 ay sumusuporta sa Dynamic Color, BadgedBox, WindowInsets at animated na lapad ng aktibong elemento. Ang BottomNavigation mula sa Material2 ay isang lumang API na walang mga feature na ito. Inirerekomenda ng Google ang paggamit ng NavigationBar para sa mga bagong proyekto at paglipat ng mga umiiral na proyekto.

Bakit muling nililikha ang screen kapag pinindot ang elemento ng BottomNavigation?

Ang problema ay ang kawalan ng saveState at restoreState sa navigate(). Kung wala ang mga ito, hindi ini-save ng NavController ang estado ng nakaraang tab. Idagdag ang popUpTo(startDestination) { saveState = true } at restoreState = true sa NavOptions upang mapanatili ang LazyColumn, scroll at mga input field.

Paano i-customize ang animation ng paglipat sa pagitan ng mga tab?

Ang animation ng paglipat ay kinokontrol sa antas ng NavHost, hindi ng BottomNavigation. Magdagdag ng composable(route, enterTransition, exitTransition) na may custom na animation. Para sa BottomNavigation, tipikal ang fading animation (fadeIn + fadeOut) na may tagal na 300ms.

Buod

  • BottomNavigation (NavigationBar sa M3) — ibabang panel para sa paglipat sa pagitan ng 3–5 pangunahing screen ng application
  • NavigationBarItem — elemento ng panel na may icon, label, badge at estado ng pagpili
  • Integrasyon sa NavController ay nangangailangan ng popUpTo, launchSingleTop at restoreState para sa tamang pamamahala ng stack
  • Material3 NavigationBar ay sumusuporta sa Dynamic Color, BadgedBox, WindowInsets at animation ng aktibong elemento
  • BadgedBox — component para sa mga badge ng notification na may numero o tuldok sa icon ng elemento
  • Estado ng pagpili ay kinakalkula mula sa currentBackStackEntryAsState para sa pag-sync sa NavController
  • Upang itago ang panel sa mga child screen, gamitin ang conditional rendering sa Scaffold bottomBar batay sa listahan ng ruta

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din