NavHost Multi module
In NavHost we saw how we can create a component that can manage the state of multiple navigators at the same time. In this section we will learn how to do that in a multi module project.
First, if you haven't read Multi Module Navigation, read that first then come back, it will give a bit more context about the example being used below.
We will use the same structure that we had in Multi Module Navigation, where we have two features: Profile and Home, but instead of them being individual screens, now we will be using them in a NavHost
.
We will add two more features: Onboarding and BottomNav. Onboarding will be the first screen when we open the app, BottomNav will be the screen holding the NavHost
.
Updating Home and Profile modules
Now that those features are tabs, we can also add a StackKey
to their respective navigation modules:
HomeNavigation.kt
@Parcelize
object HomeStackKey: StackKey
ProfileNavigation.kt
@Parcelize
object ProfileStackKey: StackKey
Onboarding feature module
feature:onboarding
will depend on feature:onboarding:navigation
and feature:bottomnav:navigation
First, inside :feature:onboarding:navigation
module we can declare our onboarding key:
OnboardingNavigation.kt
@Parcelize
class OnboardingKey(): NavigationKey
Then, inside our :feature:onboarding
we can create an extension function on NavigatorConfigBuilder
to tie our key to a Composable:
OnboardingNavigationBuilder.kt
fun NavigatorConfigBuilder.onboardingNavigation() {
screen<OnboardingKey> { key -> OnboardingScreen() }
}
class OnboardingScreen() {
val navigator = requireLocalNavigator()
Column {
Text("Onboarding!")
Button(onClick = { navigator.push(BottomNavKey()) }) {
Text("Go to Bottom nav")
}
}
}
BottomNav feature module
feature:bottomnav
will depend on feature:bottomnav:navigation
, feature:home:navigation
and feature:profile:navigation
First, inside feature:bottomnav:navigation
module we can declare our bottom nav key:
BottomNavNavigation.kt
@Parcelize
class BottomNavKey: NavigationKey
Then, inside our :feature:bottomnav
we can create an extension function on NavigatorConfigBuilder
to tie our key to a Composable, however here we will actually be expecting the navigation for both home and profile. We can pass those as parameters to our bottomNavNavigation
function.
OnboardingNavigationBuilder.kt
fun NavigatorConfigBuilder.bottomNavNavigation(
homeNavigation: NavigatorConfigBuilder.() -> Unit,
profileNavigation: NavigatorConfigBuilder.() -> Unit,
) {
screen<BottomNavKey> { key ->
BottomNavScreen(
homeNavigation = homeNavigation,
profileNavigation = profileNavigation
)
}
}
Then we pass them down to our screen where we will create a NavHost
:
class BottomNavScreen(
homeNavigation: NavigatorConfigBuilder.() -> Unit = {},
profileNavigation: NavigatorConfigBuilder.() -> Unit = {}
) {
val homeNavigator = rememberNavigator { homeNavigation() }
val profileNavigator = rememberNavigator { profileNavigation() }
val navHost = rememberNavHost(
initialKey = HomeStackKey,
entries = setOf(
StackEntry(HomeStackKey, homeNavigator),
StackEntry(ProfileStackKey, profileNavigator)
)
)
navHost.NavContainer()
}
App module
Finally, we can tie everything up together in our app module!
val navigator = rememberNavigator(
initialKey = OnboardingKey()
) {
onboardingNavigation()
bottomNavNavigation(
homeNavigation = { homeNavigation() },
profileNavigation = { profileNavigation() }
)
}
navigator.NavContainer()
Last updated