android-jetpack-composejetpack-compose-navigation

Display Bottom Navigation Only on Specific Composables in Jetpack Compose


What I want is that my bottom navigation to only be shown in specific Composables like home screen and settings screen. The problem is the bottom navigation is also shown in the login and sign-up screens which sabotages the login/sign-up normal behavior.

The problem with the code that I'm using is that either it removes the bottom navigation from all the Screens or it shows it in all of them. This is the code that I'm using:

val navController = rememberNavController()

Scaffold(
    bottomBar = {
        val currentDestination = navController.currentBackStackEntry?.destination?.route
        val shouldDisplayBottomBar = when (currentDestination) {
            Home.route, Quiz.route, FeedBack.route, Settings.route -> true
            else -> false
        }
        if (shouldDisplayBottomBar) {
            MyBottomNavigation(navController = navController, shouldDisplay = true)
        }
    }
)
Here is MyBottomNavigation function:
`@Composable
fun MyBottomNavigation(navController: NavController, shouldDisplay: Boolean) {
    if (shouldDisplay) {
        val destinationList = listOf(
            Home,
            Quiz,
            FeedBack,
            Settings
        )
        val selectedIndex = rememberSaveable {
            mutableStateOf(0)
        }

        BottomNavigation {
            destinationList.forEachIndexed { index, destination ->
                BottomNavigationItem(
                    label = { Text(text = destination.title) },
                    selected = index == selectedIndex.value,
                    onClick = {
                        selectedIndex.value = index
                        navController.navigate(destinationList[index].route) {
                            popUpTo(Home.route)
                            launchSingleTop = true
                        }
                    },
                    icon = {
                        destination.icon?.let {
                            Icon(
                                imageVector = it,
                                contentDescription = destination.title
                            )
                        }
                    }
                )
            }
        }
    }
}
`

Solution

  • The shouldDisplayBottomBar variable is intended to update whenever the currentBackStackEntry changes. However, the issue is that navController.currentBackStackEntry captures the back stack state only once when the Scaffold is rendered and does not update afterward. This results in the bottomBar being either permanently shown or hidden throughout the app.

    To resolve this, you should use currentBackStackEntryAsState(). This will allow you to observe the current back stack entry and ensure its value is updated whenever the navController modifies the back stack. Here is the updated code:

    val navController = rememberNavController()
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    
    Scaffold(
    bottomBar = {
        val currentDestination = navBackStackEntry?.destination?.route
        val shouldDisplayBottomBar = when (currentDestination) {
            Home.route, Quiz.route, FeedBack.route, Settings.route -> true
            else -> false
        }
        if (shouldDisplayBottomBar) {
            MyBottomNavigation(navController = navController, shouldDisplay = true)
        }
      }
    )