Material3 ‐ Bottom Navigation Bar - devrath/Material-3-Design-Kit GitHub Wiki
Contents |
---|
Observation |
Demo representation |
Code |
- We use the bottom navigation bar when there is a minimum of 3 tabs and a maximum of 5
Light Theme |
Dark Theme |
---|---|
![]() |
![]() |
BottomNavigationItem.kt Contains the data for the Navigation Tab to hold the states
sealed class BottomNavigationItem(
val route:String,
val iconSelected: ImageVector,
val iconUnSelected: ImageVector,
val title: String = ""
){
// <--------- Home Screen --------->
object Home : BottomNavigationItem(
route = "home",
title = "Home",
iconSelected = Icons.Filled.Home,
iconUnSelected = Icons.Outlined.Home,
)
// <--------- Chat Screen --------->
object Chat : BottomNavigationItem(
route = "chat",
title = "Settings",
iconSelected = Icons.Filled.ChatBubble,
iconUnSelected = Icons.Outlined.ChatBubble,
)
// <--------- Settings Screen --------->
object Settings : BottomNavigationItem(
route = "settings",
title = "Settings",
iconSelected = Icons.Filled.Settings,
iconUnSelected = Icons.Outlined.Settings,
)
}
NavScreens.kt Contains all the screens
@Composable
fun ScreenHome() {
CommonScreen(screenName = "Home", backgroundColor = Color.DarkGray)
}
@Composable
fun ScreenChat() {
CommonScreen(screenName = "Chat", backgroundColor = Color.Magenta)
}
@Composable
fun ScreenSettings() {
CommonScreen(screenName = "Settings", backgroundColor = Color.Cyan)
}
@Composable
private fun CommonScreen(screenName: String, backgroundColor: Color) {
Column(
modifier = Modifier
.fillMaxSize()
.background(color = backgroundColor),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
modifier = Modifier.fillMaxWidth(),
fontSize = 30.sp,
textAlign = TextAlign.Center,
fontFamily = FontFamily.Monospace,
style = TextStyle(
color = Color.White
),
text = screenName
)
}
}
@Preview
@Composable
private fun CurrentScreen() {
ScreenHome()
}
NavigationGraph.kt It contains all a navigation host that holds all the screen composables
// Navigation graph: Contains all the screens as composable in a NavHost
@Composable
fun NavigationGraph(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = BottomNavigationItem.Home.route
) {
composable(route = BottomNavigationItem.Home.route) {
ScreenHome()
}
composable(route = BottomNavigationItem.Chat.route) {
ScreenChat()
}
composable(route = BottomNavigationItem.Settings.route) {
ScreenSettings()
}
}
}
BottomNavContent.kt Content composable that holds scaffold that in turn holds bottom bar and navigation host
@Composable
fun BottomNavContent(modifier: Modifier = Modifier) {
// Data items to have the Bottom tabs
val navItems = remember {
mutableStateListOf(
BottomNavigationItem.Home,
BottomNavigationItem.Chat,
BottomNavigationItem.Settings
)
}
// The state "rememberSavable" helps to save the state in configuration changes, We can save in viewmodel also
var selectedItemIndex by rememberSaveable { mutableIntStateOf(0) }
// Keeping track of navigation
val navController = rememberNavController();
// Scaffold: it contains bottom navigation bar and a NavHost(Contains all screens) for each screen
Scaffold(
bottomBar = {
NavigationBar {
navItems.forEachIndexed { index, item ->
NavigationBarItem(
// If both the index are same, return true indicating it is selected
selected = (selectedItemIndex == index),
onClick = {
selectedItemIndex = index
navController.navigate(item.route)
},
label = {
Text(text = item.title)
},
icon = {
Icon(
imageVector = if (selectedItemIndex == index) {
item.iconSelected
} else {
item.iconUnSelected
},
contentDescription = item.title
)
},
)
}
}
}
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(it)
) {
NavigationGraph(navController)
}
}
}
BottomNavigationBarActivity.kt Activity that contains a single composable holding the content of the screen
class BottomNavigationBarActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialAppTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
ScreenContent()
}
}
}
}
}
@Composable
fun ScreenContent(modifier: Modifier = Modifier) {
BottomNavContent()
}
@Preview(showBackground = true)
@Composable
fun CurrentScreenPreview() {
MaterialAppTheme {
ScreenContent()
}
}