An opinionated fast Ballast Navigation set-up for Compose multiplatform (Android & iOS for now)
Android:
implementation("com.dilivva.ballastnavigationext:ballastnavigationext:LATEST")
Multiplatform: Android & iOS
val commonMain by getting {
dependencies {
//put your multiplatform dependencies here
api("com.dilivva.ballastnavigationext:ballastnavigationext:LATEST")
}
}
Extend the BaseRoute
interface:
enum class MainRoute(
override val route: String
): BaseRoute{
Home("/home"),
SignIn("/sign-in"),
SignUp("/sign-up"),
ForgotPassword("/forgot-password"),
Dashboard("/dashboard?email={?}"),
Profile("/profile");
}
More on Ballast Route Matching
@Composable
fun MainNavigation() {
val applicationScope = rememberCoroutineScope()
val navigator = rememberNavigator(applicationScope, MainRoute.values())
}
The rememberNavigator
assumes your first defined route in your
enum class in the initial route. You can override that by passing in
a callback that will return your desired initial route:
@Composable
fun MainNavigation() {
var isLoggedIn by remember { mutableStateOf(false) }
val applicationScope = rememberCoroutineScope()
val navigator = rememberNavigator(applicationScope, MainRoute.values()) {
if (isLoggedIn) MainRoute.Dashboard else MainRoute.Home
}
}
Destination(
navigator = navigator,
onNavigate = {
when (it) {
//Handle changes here...
}
}
)
Navigate to a screen:
navigator.navigate(MainRoute.SignIn)
Navigate back
navigator.navigateUp()
Navigate to a screen popping up backstack to a particular screen:
navigator.navigateWithPop(destination = MainRoute.Profile, popUpTo = MainRoute.Home)
Navigate to a screen after popping the backstack:
navigator.navigateWithPopAll(destination = MainRoute.Profile)
Ballast Navigation supports passing data between destinations using query or path parameters. Read more
To pass data, just override the extras
callback of any of the
navigate**
function:
navigator.navigate(MainRoute.Profile){
pathParameter("user","john").queryParameter("email","john@gmail.com")
}
Device Back press (Android):
The library automatically handles device back pressed, if you want
to override that, pass in a value for onDeviceBackPressed
:
Destination(
//..//
onDeviceBackPressed = {
if (it == MainRoute.Dashboard){
//close app
}else{
navigator.navigateUp()
}
}
)
There's a default enter and exit animations (Slide in/out), but you can
override that and pass in your own enter and exit animations to the
animateIn
and animateOut
callbacks:
Destination(
//..//
animateIn = { },
animateOut = { }
)
If a route cannot be matched noDestination
callback will be invoked
the library automatically does nothing, you can override that.
Deep links are supported automatically with few extra setups
Define your scheme in the android Manifest:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Accepts URIs that begin with "ballast://dashboard” -->
<data android:scheme="ballast"
android:host="app" />
</intent-filter>
That's all!
Test your deep link:
adb shell am start -W -a android.intent.action.VIEW -d "ballast://app/dashboard?email=dilivva@email.com"
The above command deep links to the dashboard screen passing in an email
address. So when deep linking to a screen in your app the pattern
is as follows
scheme://host/screen
.
Define your URL scheme:
Lastly let the library handle the linking:
ContentView().onOpenURL { link in
//Set up to support URL scheme
DeepLinkResult.companion.setUrl(url: link.absoluteString)
}
That's all!!
Android:
android_8dOfvdjN.mp4
iOS:
ios.mp4
Ballast: for the awesome routing/navigation library
BallastNavigationExt is licensed under the MIT License, see LICENSE.md.