Voyant is an extension library for Voyager and Jetpack Compose Navigation it enables developers to use native navigation for Apple platforms.
Like What you see?
Buy me a coffee
- For Voyager
implementation("io.github.kashif-mehmood-km:voyant-voyagerx:latest")
- For compose Navigation
implementation("io.github.kashif-mehmood-km:voyant-navigation-compose:latest")
- For Swift UI there is one small extra step
struct NavigationControllerWrapper: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UINavigationController {
// MainKt.MainViewController() is the entry point of the app wrapped inside a uinavigation controller
//so you can get the navigation controller from the view controller
let navigationController = UINavigationController(rootViewController: MainKt.MainViewController())
navigationController.interactivePopGestureRecognizer?.isEnabled = true
return navigationController
}
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {
}
}
// content view being used inside AppDelegate to set the root view controller
struct ContentView: View {
var body: some View {
NavigationControllerWrapper()
.edgesIgnoringSafeArea(.all)
}
}
- Android
- IOS
- WasmJS
- JVM
Voyager
@Composable
@OptIn(ExperimentalMaterialApi::class)
fun VoyagerNavigation() {
Voyant(
content = { BottomSheetNavigator { Navigator(ScreenA()) } },
wrapper = { content -> AppTheme { content() } })
}
Voyant
is the entry point for the library, it takes two parameterscontent
andwrapper
wherecontent
is the main content of the app andwrapper
is the wrapper around the content. Pass theNavigator
as the content andBottomSheetNavigator
as the wrapper.- Instead of using methods of voyager library like
push
usepushX
instead. Similar forBottomSheetNavigator
useshowX
instead ofshow
-
showX has two extra parameters
fun BottomSheetNavigator.showX( screen: Screen, skipHalfExpanded: Boolean = false, fixedHeight: Double = 0.0 )
skipHalfExpanded
andfixedHeight
which are optional and can be used to skip the half expanded state and set the fixed height of the bottom sheet respectively for IOS.
Navigation Compose
Inherit your screens from this VoyantRoute
interface
interface VoyantRoute{
@Composable
fun content(navController: NavController)
}
create your screens like this
@Serializable
object MovieScreenRoute : VoyantRoute {
@Composable
override fun content(navController: NavController) {
Box(modifier = Modifier.fillMaxSize()) {
Text(
"Movie Screen",
modifier = Modifier.padding(16.dp).align(Alignment.Center).clickable {
navController.navigateX(MovieDetailsScreenRoute)
})
}
}
}
define the navgraph and use the serialized version of routes and get them from back stack entry
@Composable
fun NavigationCompose() {
Voyant(content = {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = MovieScreenRoute) {
composable<MovieScreenRoute> { backStackEntry ->
val searchDomainModel = backStackEntry.toRoute<MovieScreenRoute>()
searchDomainModel.content(navController)
}
composable<MovieDetailsScreenRoute> { navBackStackEntry ->
val movieDetailsScreenRoute =
navBackStackEntry.toRoute<MovieDetailsScreenRoute>()
movieDetailsScreenRoute.content(navController)
}
}
}, wrapper = { content ->
AppTheme {
content()
}
})
}
- Use the Voyant function to wrap the
NavHost
andAppTheme
or any other wrapper such as koinApplication. - Pass the
NavHost
as the content andAppTheme
or any other wrapper as the wrapper.
You can check the composeApp
for more details on both navigation compose
and voyager
usage.
The library is in an experimental stage, APIs can change/break.
Contributions
Contributions are Welcome! Before submitting a pull request, please open an issue so we can discuss the proposed changes and collaborate on improving the project.
Feature Requests Feature requests are encouraged, and I’ll do my best to address them as quickly as possible.
MIT License