0

When I click on any of my BottomNavigation items I get an IllegalStateException.

This is my initial code that I expected to work

    BottomNavigation(contentColor = colorResource(id = R.color.white)) {
    val navBackStackEntry by navController.currentBackStackEntryAsState()
    val currentRoute = navBackStackEntry?.destination?.route
    menuItems.forEach {
        BottomNavigationItem(
            label = {Text(text=it.title)},
            alwaysShowLabel = true,
            selectedContentColor = Color.White,
            unselectedContentColor = Color.Gray,
            selected = currentRoute == it.route,
            onClick = {
                      navController.navigate(it.route) {
                          navController.graph.startDestinationRoute?.let {
                              route ->
                              popUpTo(route) {
                                  saveState = true
                              }
                          }
                          launchSingleTop = true
                          restoreState = true
                      }
            },
            icon= {Icon(imageVector = it.icon, contentDescription = it.title)}
        )
    }
}

I tried different variations of the code from the web but they all throw the same exception

Also tried setting alwaysShowLabel to false

asd
  • 13
  • 4

1 Answers1

0

This is the proper way to implement BottomNavigation in jetpack compose.

1.Create a sealed class with all the screen as objects

sealed class BottomNavClass (
    val route : String,
    val title : String,
    val icon : ImageVector
){
    object Home : BottomNavClass(
        route = "home",
        title = "Home",
        icon = Icons.Default.Home
    )
    object Profile : BottomNavClass(
        route = "profile",
        title = "Profile",
        icon = Icons.Default.Person
    )
    object Saved : BottomNavClass(
        route = "saved",
        title = "Saved",
        icon = Icons.Default.Favorite
    )

}
  1. Create a NavGraph function containing of the composable function assigning the routes to screen
@Composable
fun BottomNavGraph(navController: NavHostController) {
NavHost(navController = navController, startDestination = BottomNavClass.Home.route){
        composable(route = BottomNavClass.Home.route){
           
        }
        composable(route=BottomNavClass.Settings.route){
        }
        composable(route = BottomNavClass.Profile.route)
        ){
            
         
        }
      }
  1. An extension function for the BottomNavigation composable for defining the color and navigations.

@Composable
fun RowScope.AddItem(
    screen : BottomNavClass,
    currentDestination : NavDestination?,
    navController: NavHostController
) {
    BottomNavigationItem(label = {
        Text(text = screen.title)
    },
        icon = {
            Icon(imageVector = screen.icon, contentDescription = "")
        },
        selected = currentDestination?.hierarchy?.any{
            it.route == screen.route
        } == true,
        onClick = {
            navController.navigate(screen.route){
                popUpTo(navController.graph.findStartDestination().id)
                launchSingleTop = true
            }
        },
        unselectedContentColor = LocalContentColor.current.copy(alpha = ContentAlpha.disabled)
        )
}
  1. A composable for the BottomNavigationBar
@Composable
fun BottomBar(navController: NavHostController) {

    val screens = listOf(
        BottomNavClass.Home,
        BottomNavClass.Saved,
        BottomNavClass.Profile
    )

    val navBackStackEntry by navController.currentBackStackEntryAsState()

    val currentDestination = navBackStackEntry?.destination

    BottomNavigation {
        screens.forEach{
            AddItem(screen = it, currentDestination = currentDestination, navController = navController)
        }
    }
}
  1. And at last placing the BottomBar in your main screen using the scaffold.
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MainScreen() {

    val navController = rememberNavController()

    Scaffold(
        bottomBar = { BottomBar(navController = navController)}
    ) {
        Surface(
            modifier = Modifier
                .fillMaxSize()
                .padding(it)
        ) {
            BottomNavGraph(navController = navController)
        }
    }

}

zaid khan
  • 825
  • 3
  • 11