Hey, I have few doubts about Navigation with Compo...
# compose
m
Hey, I have few doubts about Navigation with Compose (my first time using it) - maybe someone can help me with: 1. Should we reuse the NavController or each NavHost should have one? E.g., a NavHost that internally has a screen with a tab and another NavHost. 2. Is there a way to create a NavGraphBuilder without a NavController? I would like to create one using Dagger + Multibinding and reuse it in 2 NavHost. Thank you in advance.
👍 1
👍🏼 1
i
What design pattern led you to consider using multiple NavHosts?
m
Consider the following scenario: I have a sign in screen and a home screen, where the home has a bottom navigation bar. To handle the screen level navigation, I use a NavHost placed in the screen level (activity root view). That let me do: Sign In screen -> Home screen or Sign In screen -> Sign Up screen. To handle the home level navigation, I use a NavHost placed inside the Home screen (home container view). That let me handle situations like: Home screen (Feeds tab) -> Home screen (feed item details, showed inside Feeds tab). That explains it conceptually - but the app is huge and my current scenario is much more complex (parts of the application takes part of the screen that have their own back-stack, etc). My limited understand is that it should be 2+ NavHost, where each one has its own NavGraph and NavController. Let me know if I can help with more data in any area, and thank you for answering! 🙏
i
What resources have you looked at for doing login in Navigation? We've talked about that particular topic quite a bit here before, e.g.: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1626727460044100?thread_ts=1626726997.043700&cid=CJLTWPH7S
We've talked about why login should never be the start destination of your app here too: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1617812338353700?thread_ts=1617805109.343700&cid=CJLTWPH7S
"Tabs" tend to be a loaded term - there's tabs along the top and there's a bottom nav bar. Those are considered very different from a navigation point of view - Material recommends that tabs don't have their own stacks, so any navigation from a tab destination would replace the entire content of the window (including the tabs) as you move to those sub-destinations. That's different from the persistent bottom nav bar, where Navigation already supports separate stacks for each bottom nav item
m
For the login logic: we don't use it as a start destination and we are handling it properly - actually, I saw those messages before and I'm aware of it. Thank you! In your third comment, what do you mean with "persistent bottom nav bar"? Do you have any link with examples on how to do it with Compose? I'm reading Navigation with Compose documentation and in the example, I see a NavHost inside BottomNavigation:
Copy code
val navController = rememberNavController()
// Screen level
Scaffold(
  bottomBar = {
    BottomNavigation {
      val navBackStackEntry by navController.currentBackStackEntryAsState()
      val currentDestination = navBackStackEntry?.destination
      items.forEach { screen ->
        BottomNavigationItem(
          icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
          label = { Text(stringResource(screen.resourceId)) },
          selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
          onClick = {
            navController.navigate(screen.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
              popUpTo(navController.graph.findStartDestination().id) {
                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
            }
          }
        )
      }
    }
  }
) { innerPadding ->
  // -> Here is the nested NavHost <-
  NavHost(navController, startDestination = Screen.Profile.route, Modifier.padding(innerPadding)) {
    composable(Screen.Profile.route) { Profile(navController) }
    composable(Screen.FriendsList.route) { FriendsList(navController) }
  }
}
https://developer.android.com/jetpack/compose/navigation#bottom-nav My understanding from the example above is that: if I need to do a "full screen" navigation I will use the root NavHost but if I'm at (example) a home screen with bottom navigation, I need a second NavHost inside... 🤔
i
m
Ah, I see. The recommendation is to actually hide the bottom navigation based in your destination... that will give the impression of full screen navigation. Gotcha. I will play around with the idea and see how it goes for our cases. Thank you @Ian Lake.