Bottom Navigation Bar with Jetpack Compose

Photo by Axel Antas-Bergkvist on Unsplash

Note: You need to have Android Studio Arctic Fox to use Jetpack Compose in your project.

Adding libraries

Open your project-level build.gradle file, and add the following extension:

buildscript {
ext {
compose_version = '1.0.0-beta08'
}
//....
}

Open your app-level build.gradle file, and add the following

android {
//..
buildFeatures {
compose true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
kotlinCompilerVersion '1.5.10'
}
}
dependencies {

implementation "androidx.compose.ui:ui:$compose_version"
implementation androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.0-beta01'
implementation "androidx.navigation:navigation-runtime-ktx:2.4.0- alpha02@aar"
implementation "androidx.navigation:navigation-compose:2.4.0-alpha02"

}

Now create the TopBar and Bottom Navigation Bar

TopBar

In your compose activity, add the following code outside the main class. We have used TopAppBar composable function and set the title, background color and content color.

@Composable
fun TopBar() {
TopAppBar(
title = { Text(text = stringResource(R.string.app_name), fontSize = 18.sp) },
backgroundColor = colorResource(id = R.color.teal_700),
contentColor = Color.White
)
}

Bottom Navigation Bar

To add Bottom Navigation Bar, we first need to think about the tabs in it. To show tabs, we will create a sealed class BottomNavigationItem with different options.

Create sealed class as follows.

sealed class BottomNavigationItem(var route: String, var icon: Int, var title: String) {
object One : BottomNavigationItem("one", android.R.drawable.ic_media_play, "One")
object Two : BottomNavigationItem("two", android.R.drawable.ic_media_play, "Two")
object Three : BottomNavigationItem("three", android.R.drawable.ic_media_play, "Three")
object Four : BottomNavigationItem("four", android.R.drawable.ic_media_play, "Four")
object Five : BottomNavigationItem("five", android.R.drawable.ic_media_play, "Five")
}

Next, similar to TopAppBar, add following code outside of your main class.

@Composable
fun BottomNavigationBar() {
val items = listOf(
BottomNavigationItem.One,
BottomNavigationItem.Two,
BottomNavigationItem.Three,
BottomNavigationItem.Four,
BottomNavigationItem.Five
)
BottomNavigation(
backgroundColor = colorResource(id = R.color.teal_700),
contentColor = Color.White
) {

items.forEach { item ->
BottomNavigationItem(
icon = { Icon(painterResource(id = item.icon), contentDescription = item.title) },
label = { Text(text = item.title) },
selectedContentColor = Color.White,
unselectedContentColor = Color.White.copy(0.4f),
alwaysShowLabel = true,
selected = false,
onClick = {
//...

}
}
)
}
}
}

As we have created the composable functions for TopAppBar and BottomNaviagionBar. Now its time to put them together. Add following composable function outside the main class.

@Composable
fun MainScreen() {
Scaffold(
topBar = { TopBar() },
bottomBar = { BottomNavigationBar(navController) }
)
}

Now, its time to create screens for different tabs in BottomNavigationBar

To create the screens, create a file and add following composable functions in it. Here we have FirstScreen, SecondScreen, ThirdScreen, FourthScreen, FifthScreen composable functions.

@Composable
fun FirstScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
.wrapContentSize(Alignment.Center)
) {
Text(
text = "First View",
fontWeight = FontWeight.Bold,
color = Color.Black,
modifier = Modifier.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center,
fontSize = 25.sp
)
}
}


@Composable
fun SecondScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
.wrapContentSize(Alignment.Center)
) {
Text(
text = "Second View",
fontWeight = FontWeight.Bold,
color = Color.Black,
modifier = Modifier.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center,
fontSize = 25.sp
)
}
}

@Composable
fun ThirdScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
.wrapContentSize(Alignment.Center)
) {
Text(
text = "Third View",
fontWeight = FontWeight.Bold,
color = Color.Black,
modifier = Modifier.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center,
fontSize = 25.sp
)
}
}

@Composable
fun FourthScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
.wrapContentSize(Alignment.Center)
) {
Text(
text = "Fourth View",
fontWeight = FontWeight.Bold,
color = Color.Black,
modifier = Modifier.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center,
fontSize = 25.sp
)
}
}

@Composable
fun FifthScreen() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
.wrapContentSize(Alignment.Center)
) {
Text(
text = "Fifth View",
fontWeight = FontWeight.Bold,
color = Color.Black,
modifier = Modifier.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center,
fontSize = 25.sp
)
}
}

To attach above created screens with BottomNavigationBar, first create the following composable function Navigate. It takes two parameters, NavHostController and route(String). NavHost is a NavGraphBuilder.

@Composable
fun Navigation(navController: NavHostController, route: String) {
NavHost(navController = navController, startDestination = route) {
composable(BottomNavigationItem.One.route) {
FirstScreen()
}
composable(BottomNavigationItem.Two.route) {
SecondScreen()
}
composable(BottomNavigationItem.Three.route) {
ThirdScreen()
}
composable(BottomNavigationItem.Four.route) {
FourthScreen()
}
composable(BottomNavigationItem.Five.route) {
FifthScreen()
}

}
}

In the MainScreen(), we create the Navigation Controller, and we’re passing it to the BottomNavigationBar and Navigation created above.

@Composable
fun MainScreen() {
val navController = rememberNavController()
Scaffold(
topBar = { TopBar() },
bottomBar = { BottomNavigationBar(navController) }
) {
Navigation(navController = navController, BottomNavigationItem.One.route)

}
}

Next, in the BottomNavigationBar, add the parameter navController, and create the navBackStackEntry and the currentRoute.

Using the currentRoute, we check if we have to highlight the bar item or not, and we navigate to the view using the navigate() method

@Composable
fun BottomNavigationBar(navController: NavController) {
val items = listOf(
BottomNavigationItem.One,
BottomNavigationItem.Two,
BottomNavigationItem.Three,
BottomNavigationItem.Four,
BottomNavigationItem.Five
)
BottomNavigation(
backgroundColor = colorResource(id = R.color.teal_700),
contentColor = Color.White
) {
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 = Color.White,
unselectedContentColor = Color.White.copy(0.4f),
alwaysShowLabel = true,
selected = currentRoute == item.route,
onClick = {
navController.navigate(item.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
navController.graph.startDestinationRoute?.let { route ->
popUpTo(route) {
saveState = true
}
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
}
)
}
}
}

Thats It. You are ready with BottomNaviagtionBar Integration with Compose and Jetpack Navigation.

Find Code on Github — https://github.com/radaurgaurav/BottomNavigationInCompose

--

--

--

Android App Developer, Yoga Practitioner, Running Enthusiast

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Detail Page Design using Jetpack Compose

How to use Firebase on Android without the google-services plugin

Hacking using android continues…

Handle LiveData Observer properly in ViewModel Testing

Understand the Activity Lifecycle

OpenMRS Android Client

Implement HMS Map Kit with Flutter

Setting up the consent SDK for AdMob on Android

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Gaurav

Gaurav

Android App Developer, Yoga Practitioner, Running Enthusiast

More from Medium

Metawallet application Release

IOS MetaWallet App store Release

How we increased Kubernetes node capacity from 64 nodes to 2000+

How To Delete or Remove Apps On Android Device