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।
টেক্সট লেবেলের দৈর্ঘ্য ১২টি অক্ষর (ল্যাটিন) বা ৮টি অক্ষর (সিরিলিক) এর বেশি হওয়া উচিত নয়। দীর্ঘ লেবেল ইলিপসিস দিয়ে কাটা হয়। লেবেলের জন্য, 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 অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন