I'm trying to wrap my head around the navigation a...
# compose
j
I'm trying to wrap my head around the navigation and I've got a bottom Nav bar that's working great so far and can switch between screens from the bottom. I need to implement stack views with back buttons inside each bottom nav bar tab. So when a user starts switching views inside a tab the current screen sticks if they click on another tab the state of the other tab is remembered. I'm reading over this (https://medium.com/google-developer-experts/navigating-in-jetpack-compose-78c78d365c6a) and it looks like kind of like what I need but unsure how it jives with a bottom nav bar. And this is my bottom nav bar that I pulled out of a demo app
Copy code
@Composable
fun Navigation(user: FinUser, navController: NavHostController) {
    NavHost(navController, startDestination = NavigationItem.MapScreen.route) {
        composable(NavigationItem.Account.route) {
            Account(user = user)
        }
        composable(NavigationItem.History.route) {
            History(user = user)
        }
        composable(NavigationItem.MapScreen.route) {
            MapScreen(user = user)
        }
        composable(NavigationItem.Promo.route) {
            Promo(user = user)
        }
        composable(NavigationItem.Help.route) {
            Help(user = user)
        }
    }
}

@Composable
fun BottomNavigationBar(user: FinUser, navController: NavController) {
    val items = listOf(
        NavigationItem.Account,
        NavigationItem.History,
        NavigationItem.MapScreen,
        NavigationItem.Promo,
        <http://NavigationItem.Help|NavigationItem.Help>
    )
    BottomNavigation(
        backgroundColor = MaterialTheme.colors.primary,
        contentColor = Color.White
    ) {
        val navBackStackEntry by navController.currentBackStackEntryAsState()
        val currentRoute = navBackStackEntry?.destination?.route
        items.forEach { item ->
            BottomNavigationItem(
                icon = { Icon(item.icon, contentDescription = item.iconName) },
                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
                    }
                }
            )
        }
    }
}
🧵 5
c
@Jason Inbody can you edit your post to put the code in this thread please? https://kotlinlang.slack.com/archives/CJLTWPH7S/p1616265877303000
j
Please move the code snippet into the thread 🙂 Yeah, we wrap our
NavHost
in a
Scaffold
and show/hide the bottom nav based on the route. You'll want to look at the
currentBackStackEntryAsState
and check if you have a route that should have the bottom nav present. Assuming your
NavigationItem
is an enum, you can probably implement something very easily 🙂
c
@jossiwolf any tips for what to do if I have bottom nav implemented like that and it works great, but then on certain pages that require login, the bottom bar flashes and then the user is sent to login screen. The nav bar flash is pretty jarring. Wanted to hear your 2 cents.
j
@Colton Idle I think a lot of this depends on your nav graph architecture but I'd need to see more details. Feel free to open a new thread and tag me or shoot me a DM 🙂
c
@jossiwolf Is this still the only way to do this? For this we'll need a "global" currentScreen in the main composable that is used to set/unset the topbar, bottomNavbar, etc. It would have been better if a navGraph can be used inside the Scaffold for botttomNavBar to use. This recommended arch makes the BottomNavBar composable the "main composable".