Creating a Bottom Navigation Bar with Jetpack Compose
Hi Kotlin enthusiasts!
In this article I am going to show you how you can design bottom navigation bar in jetpack compose.
Navigation with Jetpack Compose
At first, Compose did not offer any native way of navigating screens, we had to implement our own navigation system, keeping track of back stacks and back button clicks, and this approach was very difficult to maintain as the number of screens grew and the app scaled.
Setting Up the Project
Create a new project and add the Jetpack Compose dependencies in your build.gradle
file.
dependencies {
implementation 'androidx.compose.ui:ui:1.0.0'
implementation 'androidx.compose.material:material:1.0.0'
implementation 'androidx.navigation:navigation-compose:2.4.0-alpha01'
}
Now create a sealed class with name BottomNavItem with bottom navigation item title, item icon and item route which we will use later for navigation between screens just like below:
sealed class FarmerFinanceBottomNav(
var title: String,
var icon: Int,
var screen_route: String
) {
object Home : FarmerFinanceBottomNav("Home", R.drawable.ic_finance_home, "home")
object FarmerList :
FarmerFinanceBottomNav("Onboarded Farmers", R.drawable.ic_finance_farmerlist, "farmer_list")
object Profile : FarmerFinanceBottomNav("Profile", R.drawable.ic_finance_profile, "profile")
}
Building the Bottom Navigation Bar
Now, let’s build the Bottom Navigation Bar using the BottomNavigation
composable (create a function to define bottom navigation, its item, handling bottom navigation backstack and defining start destination.)
@Composable
fun BottomNavigation(navController: NavController) {
val items = listOf(
FarmerFinanceBottomNav.Home,
FarmerFinanceBottomNav.FarmerList,
FarmerFinanceBottomNav.Profile,
)
androidx.compose.material.BottomNavigation(
backgroundColor = ColorWhite,
contentColor = Primary100Color
) {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = navBackStackEntry?.destination?.route
items.forEach { item ->
BottomNavigationItem(
icon = {
Icon(
painterResource(id = item.icon),
contentDescription = item.title
)
},
label = { Text(text = item.title) },
selectedContentColor = Primary100Color,
unselectedContentColor = Neutral70Color,
alwaysShowLabel = true,
selected = currentRoute == item.screen_route,
onClick = {
navController.navigate(item.screen_route) {
navController.graph.startDestinationRoute?.let { screen_route ->
popUpTo(screen_route) {
saveState = true
}
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
Now we need to create a composable function for handling navigation graph:
@Composable
fun NavigationGraph(navController: NavHostController) {
NavHost(navController, startDestination = FarmerFinanceBottomNav.Home.screen_route) {
composable(FarmerFinanceBottomNav.Home.screen_route) {
FarmerFinanceHomeScreen()
}
composable(FarmerFinanceBottomNav.FarmerList.screen_route) {
FarmerFinanceHomeScreen()
}
composable(FarmerFinanceBottomNav.Profile.screen_route) {
FarmerFinanceHomeScreen()
}
}
Now you need to create new composable function with Scaffold() so that you can define bottom navigation bar location, see blow:
@Composable
fun MainScreenView() {
val navController = rememberNavController()
Scaffold(
bottomBar = { BottomNavigation(navController = navController) }
) {
Column(Modifier.padding(it)) {
NavigationGraph(navController = navController)
}
}
}
Thats it now at last just call the MainScreenView() function from oncreate method of your activity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MainScreenView()
}
}
Finally the output :