BottomNavigation (Material3 में NavigationBar) एक Material Design कंपोनेंट है जो एप्लिकेशन की तीन से पांच मुख्य स्क्रीन के बीच नेविगेशन प्रदान करता है। Jetpack Compose में, निचला बार NavigationBar या BottomNavigation के माध्यम से कार्यान्वित किया जाता है, जहां प्रत्येक आइटम एक आइकन और टेक्स्ट लेबल द्वारा दर्शाया जाता है। Google Material Design (2025) के अनुसार, BottomNavigation को iOS और Android के लिए प्राथमिक नेविगेशन पैटर्न के रूप में अनुशंसित किया जाता है। पैनल WindowInsets के माध्यम से सिस्टम नेविगेशन (Gesture Navigation) की ऊंचाई के अनुसार स्वचालित रूप से समायोजित होता है। Material3 में NavigationBar डायनामिक कलर, बैज और अनुकूली मार्जिन का समर्थन करता है।
मुख्य बिंदु
BottomNavigation Material Design का एक कंपोनेंट है जो निचले नेविगेशन बार के लिए है, जो तीन से पांच मेनू आइटम प्रदर्शित करता है। Jetpack Compose में इसे BottomNavigation (Material2) और NavigationBar (Material3) कम्पोजेबल फंक्शन के माध्यम से कार्यान्वित किया जाता है। बार स्क्रीन के निचले भाग में रखा जाता है और एप्लिकेशन के प्रमुख अनुभागों तक त्वरित पहुँच प्रदान करता है।
BottomNavigation का मुख्य उद्देश्य स्क्रीन-स्तरीय गंतव्यों के बीच प्राथमिक नेविगेशन को व्यवस्थित करना है। प्रत्येक पैनल आइटम एक अलग स्क्रीन (होम, सर्च, प्रोफाइल) का प्रतिनिधित्व करता है। टैप करने पर स्क्रीन के मुख्य क्षेत्र में कंटेंट बदल जाता है। BottomNavigation नेस्टेड नेविगेशन के लिए नहीं है — इसके लिए शीर्ष पर टैब का उपयोग किया जाता है।
Material Design Guidelines (2025) के अनुसार, निचले बार में केवल वे अनुभाग होने चाहिए जो एप्लिकेशन के किसी भी बिंदु से सुलभ हों। चाइल्ड स्क्रीन पर बार को छिपाना (जैसे, विवरण पृष्ठ खोलते समय) एक मानक अभ्यास है। Compose में, BottomNavigation की दृश्यता Scaffold स्थिति या वर्तमान NavController रूट के आधार पर सशर्त रेंडरिंग के माध्यम से नियंत्रित की जाती है।
Material3 में, लीगेसी BottomNavigation के बजाय NavigationBar का उपयोग करने की अनुशंसा की जाती है। NavigationBar में डायनामिक कलर, WindowInsets सपोर्ट और बेहतर प्रेस एनिमेशन शामिल है। Google के अनुसार, NavigationBar आगे देखने वाला कंपोनेंट है, जबकि M2 का BottomNavigation केवल पिछड़ी संगतता के लिए बना हुआ है।
प्रत्येक NavigationBar आइटम NavigationBarItem कम्पोजेबल के माध्यम से कार्यान्वित किया जाता है। पैरामीटर: icon (आइकन), label (टेक्स्ट लेबल), selected (चयन स्थिति), और onClick (कॉलबैक)। NavigationBarItem स्वचालित रूप से चयनित रंग (primary) लागू करता है और सक्रियण पर आइकन आकार परिवर्तन को एनिमेट करता है।
@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 }
)
}
}
}
NavigationBarItem के लिए आइकन चयनित स्थिति के लिए भरे हुए (Filled) और अचयनित स्थिति के लिए रूपरेखित (Outlined) होने चाहिए। Material Icons दोनों सेट प्रदान करता है: Icons.Filled.Home और Icons.Outlined.Home। डिफ़ॉल्ट रूप से, NavigationBarItem चयनित के लिए भरा हुआ वेरिएंट प्रदर्शित करता है। यदि अलग प्रदर्शन की आवश्यकता है, तो आइकन को सशर्त रूप से पास करें: if (selected) Filled.X else Outlined.X।
टेक्स्ट लेबल की लंबाई 12 वर्णों (लैटिन) या 8 वर्णों (सिरिलिक) से अधिक नहीं होनी चाहिए। लंबे लेबल इलिप्सिस के साथ काट दिए जाते हैं। लेबल के लिए, maxLines = 1 और ellipsis = TextTruncation.Ellipsis का उपयोग करें। यदि लेबल हमेशा दिखाया जाना चाहिए, तो alwaysShowLabel = true पैरामीटर हटा दें (डिफ़ॉल्ट true है)।
| पैरामीटर | प्रकार | विवरण |
|---|---|---|
| icon | @Composable () -> Unit | पैनल आइटम का आइकन |
| label | @Composable (() -> Unit)? | आइकन के नीचे टेक्स्ट लेबल |
| selected | Boolean | चयनित आइटम फ्लैग |
| onClick | () -> Unit | क्लिक पर कॉलबैक |
| badge | @Composable (() -> Unit)? | सूचना गणना के साथ बैज |
सीधे selectedItem अपडेट करने से नेविगेशन ट्रिगर नहीं होता — स्क्रीन बदलने के लिए NavController के साथ एकीकरण आवश्यक है। विशिष्ट पैटर्न: NavigationBarItem में onClick navController.navigate(route) को कॉल करता है, और selectedItem वर्तमान NavController रूट से निर्धारित होता है।
NavController वर्तमान बैक स्टैक संग्रहीत करता है। यह निर्धारित करने के लिए कि कौन सा पैनल आइटम चयनित है, वर्तमान रूट (navController.currentBackStackEntryAsState().value?.destination?.route) की आइटम रूट से तुलना करें। यदि रूट मेल खाता है, तो आइटम चयनित माना जाता है। यह स्थिति दोहराव को समाप्त करता है।
@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 */ }
}
navigate() में मुख्य सेटिंग्स: popUpTo(startDestination) टैब स्विच करते समय बैक स्टैक संचय को रोकता है, launchSingleTop स्टैक में रूट दोहराव को रोकता है, और restoreState पिछली विज़िट की गई टैब की स्थिति को पुनर्स्थापित करता है। इन पैरामीटर के बिना, प्रत्येक क्लिक स्टैक में एक नई प्रविष्टि बनाता है, जिससे बैक बटन का व्यवहार गलत हो जाता है।
Material3 (M3) Material2 के BottomNavigation के प्रतिस्थापन के रूप में NavigationBar और NavigationBarItem प्रदान करता है। M3 के मुख्य लाभ: डायनामिक कलर, अनुकूली ऊंचाई, पूर्ण-चौड़ाई रिपल एनिमेशन और सिस्टम नेविगेशन के लिए WindowInsets समर्थन।
डायनामिक कलर डिवाइस वॉलपेपर (Android 12+) के आधार पर स्वचालित रूप से NavigationBar रंग चुनता है। सक्रिय आइटम primary रंग में रंगा जाता है, निष्क्रिय वाले onSurfaceVariant में। डिफ़ॉल्ट रूप से, NavigationBar Modifier.navigationBarsPadding() के माध्यम से सिस्टम नेविगेशन से ऊपर उठता है। मैन्युअल नियंत्रण के लिए, windowInsets पैरामीटर का उपयोग करें।
M3 में NavigationBar स्वचालित रूप से सक्रिय आइटम की चौड़ाई को एनिमेट करता है — आइकन बाईं ओर शिफ्ट होता है और लेबल विस्तारित होता है। एनिमेशन 300 ms तक चलता है और मानक Compose ईज़िंग का उपयोग करता है। यदि यह व्यवहार वांछित नहीं है, तो NavigationBarItem में alwaysShowLabel = true के माध्यम से हमेशा लेबल दिखाएं।
रंगों को ओवरराइड करने के लिए, colors पैरामीटर में NavigationBarColors पास करें। डिफ़ॉल्ट रूप से, NavigationBarDefaults.colors() का उपयोग किया जाता है, लेकिन कस्टम मान सेट किए जा सकते हैं: containerColor (बार पृष्ठभूमि), contentColor (आइकन रंग), indicatorColor (सक्रिय आइटम पृष्ठभूमि)। M2 के विपरीत जहां रंग BottomNavigationDefaults के माध्यम से सेट किए गए थे, M3 एक एकीकृत NavColors इंटरफ़ेस का उपयोग करता है।
यदि प्रोजेक्ट M2 (androidx.compose.material) से BottomNavigation का उपयोग करता है, तो Google M3 NavigationBar पर माइग्रेट करने की अनुशंसा करता है। माइग्रेशन में इम्पोर्ट बदलना, पैरामीटर अपडेट करना और @OptIn(ExperimentalMaterial3Api::class) जोड़ना शामिल है। M2 से BottomNavigation को पदावनत माना जाता है और इसे नई सुविधाएँ नहीं मिलती हैं।
NavigationBar स्थिति वर्तमान में चयनित आइटम का इंडेक्स संग्रहीत करती है। सरल मामलों में, remember { mutableIntStateOf(0) } का उपयोग किया जाता है। हालांकि, उत्पादन एप्लिकेशन के लिए, इंडेक्स को नेविगेशन ग्राफ के साथ सिंक्रोनाइज़ किया जाना चाहिए, न कि स्थानीय UI स्थिति होना चाहिए।
स्थिति प्रबंधन के मुख्य दृष्टिकोण: NavController-आधारित (अनुशंसित) और ViewModel-आधारित। पहले मामले में, selectedItem वर्तमान NavController रूट से गणना की जाती है। दूसरे में, ViewModel वर्तमान स्क्रीन संग्रहीत करता है, और NavigationBarItem ViewModel से StateFlow पढ़ता है। NavController-आधारित सरल है, ViewModel-आधारित जटिल तर्क (प्रमाणीकरण, A/B परीक्षण) के लिए अधिक नियंत्रण प्रदान करता है।
saveState और restoreState का उपयोग करते समय, NavController प्रत्येक टैब के अंदर LazyColumn और अन्य कंपोनेंट की स्थिति को स्वचालित रूप से सहेजता और पुनर्स्थापित करता है। यह स्क्रॉल स्थिति संग्रहीत करने के लिए ViewModel की आवश्यकता को समाप्त करता है। हालांकि, सहेजना इनपुट फ़ील्ड पर लागू नहीं होता — उन्हें SavedStateHandle या ViewModel की आवश्यकता होती है।
Badge एक कॉम्पैक्ट सूचना संकेतक है जो NavigationBarItem आइकन पर प्रदर्शित होता है। Material3 में, बैज BadgedBox के माध्यम से कार्यान्वित किया जाता है, जो आइकन को लपेटता है और बैज को ऊपरी दाएं कोने में रखता है। बैज में एक संख्या (सूचना गणना) या एक बिंदु (सरल उपस्थिति संकेतक) हो सकता है।
@Composable
fun HomeItem(unreadCount: Int) {
NavigationBarItem(
icon = {
BadgedBox(badge = {
if (unreadCount > 0) {
Badge { Text(unreadCount.toString()) }
}
}) {
Icon(Icons.Filled.Home, contentDescription = "होम")
}
},
label = { Text("Home") },
selected = false,
onClick = { }
)
}
BadgedBox स्वचालित रूप से Badge को चाइल्ड एलिमेंट के ऊपरी दाएं कोने में रखता है। यदि गणना 99 से अधिक है, तो Badge "99+" प्रदर्शित करता है। शून्य मान पर बैज छिपाने के लिए, if (count > 0) का उपयोग करें। Material3 का Badge डिफ़ॉल्ट रूप से सफेद टेक्स्ट के साथ error रंग (लाल) रखता है। BadgeDefaults.colors(containerColor, contentColor) के माध्यम से अनुकूलित करें।
Material2 में, बैज अनुपस्थित था — इसे Canvas के माध्यम से या तृतीय-पक्ष पुस्तकालयों का उपयोग करके मैन्युअल रूप से बनाना पड़ता था। Material3 ने इसे एक मूल कंपोनेंट के साथ हल किया। Android Developers (2025) के अनुसार, BadgedBox का उपयोग NavigationBar वाले 40% ऐप में किया जाता है, जिनमें से 60% अपठित संदेश प्रदर्शित करते हैं।
अक्सर पूछे जाने वाले प्रश्न
Material Design 3 से 5 आइटम की अनुशंसा करता है। तीन से कम अव्यावहारिक है (इसके बजाय Tabs का उपयोग करें)। पांच से अधिक लेबल पठनीयता और टच लक्ष्य आकार को कम करता है। यदि 5 से अधिक अनुभागों की आवश्यकता है, तो Navigation Rail (टैबलेट) या Drawer का उपयोग करें।
उन रूट की सूची परिभाषित करें जहां बार दिखाई देता है (आमतौर पर रूट रूट)। Scaffold bottomBar में, NavigationBar केवल तभी पास करें जब currentRoute bottomNavRoutes में हो। एक विकल्प बिना bottomBar के नेस्टेड स्क्रीन के लिए अलग ग्राफ वाला NavHost है।
Material3 का NavigationBar डायनामिक कलर, BadgedBox, WindowInsets और एनिमेटेड सक्रिय आइटम चौड़ाई का समर्थन करता है। Material2 का BottomNavigation इन सुविधाओं के बिना एक लीगेसी API है। Google नई परियोजनाओं के लिए NavigationBar का उपयोग करने और मौजूदा को माइग्रेट करने की अनुशंसा करता है।
समस्या navigate() में saveState और restoreState की अनुपस्थिति है। उनके बिना, NavController पिछली टैब की स्थिति को सहेजता नहीं है। LazyColumn, स्क्रॉल स्थिति और इनपुट फ़ील्ड को संरक्षित करने के लिए NavOptions में popUpTo(startDestination) { saveState = true } और restoreState = true जोड़ें।
स्विचिंग एनिमेशन NavHost स्तर पर नियंत्रित किया जाता है, BottomNavigation पर नहीं। कस्टम एनिमेशन के साथ composable(route, enterTransition, exitTransition) जोड़ें। BottomNavigation के लिए, 300ms अवधि के साथ फ़ेडिंग एनिमेशन (fadeIn + fadeOut) विशिष्ट है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें