Multi-module navigation
Voyager has built-in support for multi-module navigation. Its API is based on great DI frameworks like Koin and Kodein, so should be familiar to use.
Suppose we have the following modules:
  • app: the entrypoint of our app, contains the Activity
  • feature-home: contains the root screen (HomeScreen)
  • feature-posts: contains screens related to the posts feature (ListScreen and DetailsScreen)
  • navigation: contains the screen providers used to navigate between modules, both feature-home and feature-posts imports it
To navigate from HomeScreen to the screens on feature-posts module (ListScreen and DetailsScreen), we first need to provide them. The navigation module should declare all shared screens in the app, use the ScreenProvider interface for that.
navigation/../SharedScreen.kt
sealed class SharedScreen : ScreenProvider {
object PostList : SharedScreen()
data class PostDetails(val id: String) : SharedScreen()
}
Now use the ScreenRegistry to register these providers. This should be done in yourApplication class.
app/../MyApp.kt
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
ScreenRegistry {
register<SharedScreen.PostList> {
ListScreen()
}
register<SharedScreen.PostDetails> { provider ->
DetailsScreen(id = provider.id)
}
}
}
}
You can also create a screenModule into your feature module, that way your Application class won't be bloated by too many declarations.
ScreenModule
feature-posts/../ScreenModule.kt
val featurePostsScreenModule = screenModule {
register<SharedScreen.PostList> {
ListScreen()
}
register<SharedScreen.PostDetails> { provider ->
DetailsScreen(id = provider.id)
}
}
app/../MyApp.kt
override fun onCreate() {
super.onCreate()
ScreenRegistry {
featurePostsScreenModule()
}
}
Finally, call rememberScreen() (inside a composable function) or ScreenRegistry.get() to access your screens.
feature-home/../HomeScreen.kt
class HomeScreen : Screen {
@Composable
override fun Content() {
val navigator = LocalNavigator.currentOrThrow
val postListScreen = rememberScreen(SharedScreen.PostList)
val postDetailsScreen = rememberScreen(SharedScreen.PostDetails(id = postId))
// navigator.push(postListScreen)
// navigator.push(postDetailsScreen)
}
}

Sample

Source code here.
Copy link