Implementing A Bottom Navigation Bar Template For Android Compose

You are currently viewing Implementing A Bottom Navigation Bar Template For Android Compose

I am posting a template that can be used to create a bottom navigation bar in Android Compose. The template is minimal with two icons that lead to two simple UI screens for the user. This will lead to less adjustment needed to alter to your use case.

I added some animations to the transitions. These can be removed or changed as well.

Code

In the MainActivity

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            SampleBottomNavigationTheme {
                val navController = rememberNavController()
                Scaffold(modifier = Modifier.fillMaxSize(),
                    bottomBar = {
                        CustomNavigationBar(navController)
                    }) { innerPadding ->
                    NavHost(
                        modifier = Modifier.fillMaxWidth().padding(innerPadding),
                        navController = navController,
                        startDestination = NavigationItem.Home.route,
                        enterTransition = { slideInHorizontally() + fadeIn() },
                        exitTransition = { slideOutHorizontally() + fadeOut() },
                        popEnterTransition = { slideInHorizontally() + fadeIn() },
                        popExitTransition = { slideOutHorizontally() + fadeOut() }
                    ) {
                        composable(NavigationItem.Home.route) {
                            Home()
                        }

                        composable(NavigationItem.Other.route) {
                            Other()
                        }

                    }
                }
            }
        }
    }
}

@Composable
fun Home() {
    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Text(text = "Home")
    }
}

@Composable
fun Other() {
    Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
        Text(text = "Other")
    }
}

To keep things organized, create a separate file for each of the following.

CustomNavigationBar

@Composable
fun CustomNavigationBar(
    navController: NavController
) {

    val navigationBarItems =

        listOf(
            BottomNavigationBarItems(
                title = "Home",
                selectedIcon = Icons.Default.Home,
                unselectedIcon = Icons.Outlined.Home,
                route = NavigationItem.Home.route
            ),
            BottomNavigationBarItems(
                title = "User",
                selectedIcon = Icons.Sharp.AccountBox,
                unselectedIcon = Icons.Outlined.AccountBox,
                route = NavigationItem.Other.route
            )
        )


    var bottomNavSelectedItemIndex by remember {
        mutableIntStateOf(0)
    }

    navController.addOnDestinationChangedListener { controller, destination, arguments ->
        navigationBarItems.forEachIndexed { index, bottomNavigationBarItems ->
            if (bottomNavigationBarItems.route == destination.route)
                bottomNavSelectedItemIndex = index
        }

    }

    NavigationBar {
        navigationBarItems.forEachIndexed { index, bottomNavigationBarItems ->
            NavigationBarItem(
                selected = if (bottomNavSelectedItemIndex == index) true else false,
                onClick = {
                    bottomNavSelectedItemIndex = index
                    if (navController.currentDestination?.route != bottomNavigationBarItems.route) {
                        navController.navigate(
                            bottomNavigationBarItems.route
                        ) {
                            launchSingleTop = true
                        }
                    }
                },
                icon = {
                    Icon(
                        imageVector = if (bottomNavSelectedItemIndex == index) bottomNavigationBarItems.selectedIcon else bottomNavigationBarItems.unselectedIcon,
                        contentDescription = bottomNavigationBarItems.title
                    )
                })
        }
    }
}

NavigationItem

enum class Screen {
    Home,
    Other
}
sealed class NavigationItem(val route: String) {
    object Home : NavigationItem(Screen.Home.name)
    object Other : NavigationItem(Screen.Other.name)
}

BottomNavigationBarItems

data class BottomNavigationBarItems(
    val title: String,
    val selectedIcon: ImageVector,
    val unselectedIcon: ImageVector,
    val route : String
)

There you have it. Simple to adjust and make your own.

Hope this helps.

Leave a Reply