Bottom Navigation Bar in Jetpack Compose

Introduction

Bottom Navigation Bar is one of the most widely used feature in apps. This bottom bar can be used to navigate to different screens within an app. In this article, we will learn how to create a Bottom Navigation Bar whose visibility can be changed depending on screens' requirement using Jetpack Compose.

Steps to follow:

Step 1: Design Screens

The very first step to make the Bottom Navigation Bar is to design the screens. After opening a new project or an existing project, design all screens which has to be used in the app.

I will be creating a simple app which will have a 'Welcome' screen and three other screens. Welcome Screen will have a button in it which when clicked takes us to a screen with bottom navigation bar.

The remaining screens can be designed similarly or as per need.

Step 2: Add dependency

Go to Gradle Scripts -> build.gradle.kts (Module :app), look for dependencies and add the below code under its scope.

implementation("androidx.navigation:navigation-compose:2.7.6")

It will look something like this:

Remember you should add the latest dependency of the navigation. After adding the dependency, you can click on "Sync Now" appearing on top right or you can directly click on the button "Sync Project with Gradle Files".

Step 3: Create sealed class and objects

Create a sealed class with the name 'BottomNavigationItems,' which consists of the bottom navigation bar's item details such as route, title and icon.

You can change the icon view as per your requirement here.

Step 4: Define Routes

Create a file named 'Routes'. It allows you to define a set of distinct routes in a type-safe manner, and the sealed class ensures that all possible routes are known at compile time. Define other routes which are needed in the app here.

Step 5: Create Bottom Bar

Make a composable function which will create a bottom bar.

import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState

@Composable
fun BottomBar(
    navController: NavHostController,
    state: Boolean,
    modifier: Modifier = Modifier
) {
    val screens = listOf(
        BottomNavigationItems.Screen1,
        BottomNavigationItems.Screen2,
        BottomNavigationItems.Screen3
    )

    NavigationBar(
        modifier = modifier,
        containerColor = Color.LightGray,
    ) {
        val navBackStackEntry by navController.currentBackStackEntryAsState()
        val currentRoute = navBackStackEntry?.destination?.route

        screens.forEach { screen ->
            NavigationBarItem(
                label = {
                    Text(text = screen.title!!)
                },
                icon = {
                    Icon(imageVector = screen.icon!!, contentDescription = "")
                },
                selected = currentRoute == screen.route,
                onClick = {
                    navController.navigate(screen.route) {
                        popUpTo(navController.graph.findStartDestination().id) {
                            saveState = true
                        }
                        launchSingleTop = true
                        restoreState = true
                    }
                },
                colors = NavigationBarItemDefaults.colors(
                    unselectedTextColor = Color.Gray,
                    selectedTextColor = Color.Black,
                    selectedIconColor = Color.Black,
                    unselectedIconColor = Color.Black,
                    indicatorColor = Color.White
                ),
            )
        }
    }
}

We are using 'state' to change the visibility of bottom bar for a respective screen, if needed. If you want to change the icon's color when it is selected or unselected, you can take use of 'colors' present in 'NavigationBarItem'.

Note: If you don't want titles of icon to appear, you can simply comment the 'label' part from the 'NavigationBarItem'.

Step 6: Define NavigationGraph

'NavigationGraph' is a composable function which is declared to define the navigation structure for the app. It uses 'NavHost' consisting of composable blocks to manage different routes facilitated by 'NavHostController'. 'startDestination' is used to refer the screen from where navigation will be started.

You can add other composable blocks required for the routings within the app in the 'NavigationGraph' function.

Since, I don't want to see the bottom navigation bar on the 'Welcome' screen, I have marked 'onBottomBarVisibilityChanged' as 'false' for the 'Welcome' screen. You can change it as per your requirement.

Step 7: Update onClick of the button

We had a button on 'Welcome' screen, let's change its 'onClick' parameter. I want to navigate to Screen1 when it is clicked. Thus, we can make changes as shown below.

Step 8: Use Bottom Bar in Scaffold of MainActivity

Now, the last step is to add the 'BottomBar' function in the Scaffold of MainActivity using some conditions so that it supports change in visibility of Bottom Bar. It can be achieved as shown below.

You can run the app in an emulator or your phone and check the newly Navigation Bottom Bar designed by you.

Check the GitHub repository here: https://github.com/scoder17/Bottom-Navigation-Bar

Connect with me on LinkedIn: https://linkedin.com/in/scoder17

Connect with me on Twitter/X: twitter.com/scoder17_