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() } })
}Voyantis the entry point for the library, it takes two parameterscontentandwrapperwherecontentis the main content of the app andwrapperis the wrapper around the content. Pass theNavigatoras the content andBottomSheetNavigatoras the wrapper.- Instead of using methods of voyager library like
pushusepushXinstead. Similar forBottomSheetNavigatoruseshowXinstead ofshow -
showX has two extra parameters
fun BottomSheetNavigator.showX( screen: Screen, skipHalfExpanded: Boolean = false, fixedHeight: Double = 0.0 )
skipHalfExpandedandfixedHeightwhich 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
NavHostandAppThemeor any other wrapper such as koinApplication. - Pass the
NavHostas the content andAppThemeor 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
