I have a linear wizard created with Android Arch Navigation and I would like to start it at specific location building back stack as with natural user navigation. So I have tried this deep link building:
Bundle args = new Bundle();
args.putString("myarg", "From Widget");
new NavDeepLinkBuilder(context)
.setGraph(R.navigation.mobile_navigation)
.setDestination(R.id.step_fragment)
.setArguments(args)
.createPendingIntent().send();
The problem with this approach is that it doesn't build back stack correctly as user will be build navigating Step 1 -> Step 2 -> ... -> Step N It only holds Step 1 -> Step N, i.e. start destination and target destination of navigation graph. This is not what I want.
Second simple approach is to just call multiple times navigate()
on navController
. But as it seems simple it doesn't work
protected fun navigateTo(step: Int) {
val navController = findNavController(R.id.nav_host_fragment)
if(step >= 0 && step < stepFragments.count()) {
// go to step-th fragment
if(navController.currentDestination.id != stepFragments.first()) return
for(i in 0 until step) {
navController.navigate(stepFragments[i])
}
navController.navigate(stepFragments[step])
} else if(step == stepFragments.count()) {
// go to confirm fragment
navController.navigate(confirmFragment)
} else {
throw IndexOutOfBoundsException("Step index is out of wizard bounds!")
}
}
It navigates correctly but then the created back stack is odd, i.e. Back button seems to work, but onNavigatedListener listener from
navController.addOnNavigatedListener(this::onNavigatedListener)
is not called correctly. So I cannot listen for fragment changes in wizard. Moreover NavController seems to be break, as consecutive button listener's navController.navigate(actionId) throws error.
java.lang.IllegalArgumentException: navigation destination is unknown to this NavController
UPDATE!
Intercepting onBackPressed() with debugger seems to show that Back Button Press doesn't call navController.popBackStack() and the navController.currentDestination property doesn't change. But inside NavHostFragment the fragment is changing.
It seems that this multi-step navController.navigate() works Ok. And fixing of back-stack while pressing Back button to expected behaviour can be achieved by overriding default onBackPressed() behaviour to something like this:
//region BACK PRESSED - CUSTOM BACK STACK HANDLING
override fun onBackPressed() {
if(!findNavController(R.id.nav_host_fragment).popBackStack()) {
super.onBackPressed()
}
}
//endregion
And for the record
protected fun navigateTo(step: Int) {
val navController = findNavController(R.id.nav_host_fragment)
if(step >= 0 && step < stepFragments.count()) {
// go to step-th fragment
if(navController.currentDestination.id != stepFragments.first()) return
for(i in 0 until step) {
navController.navigate(stepFragments[i])
}
navController.navigate(stepFragments[step])
} else if(step == stepFragments.count()) {
// go to confirm fragment
navController.navigate(confirmFragment)
} else {
throw IndexOutOfBoundsException("Step index is out of wizard bounds!")
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With