How to access `navigator` in root Navigator's `onBackPressed` handler?
I have a very easy case, just accessing navigator instance in onBackPressed handler. Because LocalNavigator.currentOrThrow need in Composable context, I can't use it in that handler. how to do that?
Example:
@Composable
fun App() {
MaterialTheme {
Navigator(
screen = SplashScreen(),
onBackPressed = { screen ->
// <<------- I want accessing `navigator` instance here!!!
return@Navigator true
}
) { navigator ->
}
}
}
Thanks~
I think that it should expose navigator instance as parameter in onBackPressed handler, right?
@DevSrSouza
You can't. This is a common use case, the onBackPressed API currently does not allow this use case.
There is this open PR that fixs some bugs related to nested navigators https://github.com/adrielcafe/voyager/pull/273. I plan to get on back on it soon.
Solution I propose for now, that is what I'm currently using it in personal projects is to replicated what Voyager navigators does under the hood.
This snippet was taken from the Voyager implementation here https://github.com/adrielcafe/voyager/blob/a28fd4dab8fbdd88943974b6df4c8c77f587defc/voyager-navigator/src/commonMain/kotlin/cafe/adriel/voyager/navigator/internal/NavigatorBackHandler.kt#L11
Navigator(...) { navigator ->
BackHandler(
enabled = navigator.canPop || navigator.parent?.canPop ?: false,
onBack = {
// DO anything here with the `navigator`
if (navigator.pop().not()) {
navigator.parent?.pop()
}
}
)
CurrentScreen()
}
You don't need to access navigator instance in Navigator onBackPressed. Here is how I used
Navigator(LoadingScreen, onBackPressed = { currentScreen ->
when (currentScreen.key) {
LoadingScreen.key, IntroductionScreen.key, WelcomeScreen.key -> return@Navigator false
else -> return@Navigator true
}
}) { navigator -> ...}
In your Screen, use (you can access navigator in screen easily)
BackPressHandler { //back pressed
//Do Something
}
@Composable
fun BackPressHandler(
backPressedDispatcher: OnBackPressedDispatcher? =
LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher,
onBackPressed: () -> Unit
) {
val currentOnBackPressed by rememberUpdatedState(newValue = onBackPressed)
val backCallback = remember {
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
currentOnBackPressed()
}
}
}
DisposableEffect(key1 = backPressedDispatcher) {
backPressedDispatcher?.addCallback(backCallback)
onDispose {
backCallback.remove()
}
}
}