Closed Velord closed 4 months ago
Hi @Velord ! 👋
navigateTo
was removed a while ago, it seems like this specific page was not updated. Thank you for reporting, I will update it right away!
There is also a big ⚠️ sign on readme about a change in official library that broke usages of NavController passing in Compose Destinations Direction
class. You need to either do navController.navigate(MyDestination(myArgs).route)
or a better alternative is to do what's written here and get a hold of a DestinationsNavigator
and use that instead of the NavController
directly.
As far as the multiple back stack not working, it is not controlled by Compose Destinations. I believe it is most likely that you're missing something to make that work.
You can check specifically the sample
project of this Github repository. We use multiple back stacks there.
Or check this article:
https://medium.com/androiddevelopers/multiple-back-stacks-b714d974f134
After digging your code in 'sample' line by line I have come to my setup was wrong in a few moments. But I am still convinced that is something wrong in the library.
I made a few changes
private fun onTabClick(
isSelected: Boolean,
item: BottomNavigationDestination,
destinationNavigator: DestinationsNavigator, **// That line was changed.**
navigator: BottomNavigator,
onClick: (BottomNavigationDestination) -> Unit
) {
if (isSelected) {
// When we click again on a bottom bar item and it was already selected
// we want to pop the back stack until the initial destination of this bottom bar item
destinationNavigator.popBackStack(navigator.getStartRoute(item), false)
return
}
val direction = navigator.getDirection(item)
destinationNavigator.navigate(direction) {
// Pop up to the root of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navigator.getSupremeRoute()) { **// That line was changed.**
saveState = true
}
// Avoid multiple copies of the same destination when reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
onClick(item)
}
class SupremeNavigator(
private val navController: NavHostController
) : BottomNavigator{
override fun getDirection(route: BottomNavigationDestination): Direction = when(route) {
BottomNavigationDestination.Camera -> CameraRecordingNavGraph
BottomNavigationDestination.Demo -> DemoDestinationDestination
BottomNavigationDestination.Settings -> BottomNavigationSettingsDestinationDestination
}
override fun getGraph(): NavHostGraphSpec = BottomNavigationNavGraph
@Composable
override fun CreateDestinationsNavHostForBottom(
navController: NavHostController,
modifier: Modifier,
start: BottomNavigationDestination
) {
DestinationsNavHost(
navGraph = BottomNavigationNavGraph,
modifier = modifier,
//start = getDirection(start), **// Uncomment it for breaking multiple backstack**
navController = navController,
dependenciesContainerBuilder = {
dependency(SupremeNavigator(navController = navController))
}
)
}
override fun getStartRoute(route: BottomNavigationDestination): TypedDestinationSpec<*> = when(route) {
BottomNavigationDestination.Camera -> CameraRecordingNavGraph.startDestination
BottomNavigationDestination.Demo -> DemoDestinationDestination
BottomNavigationDestination.Settings -> BottomNavigationSettingsDestinationDestination
}
override fun getSupremeRoute(): Direction = NavGraphs.bottomNavigationGraph **// Added that**
}
So when I uncomment start = getDirection(start)
multiple back stack does not work.
Without that line all works as I expect.
What do you think it may be ?
use this snippet to see how the back stack looks like with every action you take. Hope that helps!
sorry I don’t have time to check your solution, and I’m positive this is not caused by this library. Please do let me know once you make it work 🙂
@SuppressLint("RestrictedApi")
@Composable
fun LogBackStack(navController: NavController) {
LaunchedEffect(navController) {
navController.currentBackStack.collect {
it.print()
}
}
}
fun Collection<NavBackStackEntry>.print(prefix: String = "stack") {
val stack = toMutableList()
.map {
val route = it.route()
val args = runCatching { route.argsFrom(it) }.getOrNull()?.takeIf { it != Unit }?.let { "(args={$it})" } ?: ""
"$route$args"
}
.toTypedArray().contentToString()
println("$prefix = $stack")
}
Our library is very shallow wrapper around official library. It generates code to have type safe routes, but the APIs you’re calling are the official ones, even if indirectly.
Compose Destinations doesn’t do any additional work besides just calling official libraries and passing the route of whatever the type safe object you’re using.
We have plenty of people using multiple back stacks. The linked article even if simple, has the same principle you have to follow, nothing really changes if you’re using graphs instead of normal destinations.
Where you call the LogBackStack function is also important. Make sure the LaunchedEffect inside is only triggered once.
Really wish I had time to check your implementation, I’m sure we’d be able to get to the bottom of this. Maybe try hitting Kotlin slack, maybe try to replace Compose Destination specific APIs just so more people can follow your implementation. Someone will be able to help you!
good luck 🤞
I fixed log spamming issue. It is not related to this issue.
https://github.com/Velord/ComposeScreenExample I have added step by step Vanilla Compose navigation library. And it works as expected with the same navigation patterns.
Project uses navigation libs:
This line ruins multiple back stack for sure.
//start = getDirection(start), // Fixme: this is not working
https://composedestinations.rafaelcosta.xyz/common-use-cases/bottom-bar-navigation
navController.navigateTo
API does not havenavigateTo
function.My click on tab is:
When line
navController.navigate(navigator.getDirection(item).route)
ends with 'route' App builds but multiple back stack does not work. Everytime start route will be applied when user clicks on tab.Let's change line to
navController.navigate(navigator.getDirection(item))
'route' is omitted. App builds. When user clicks on tab error is present:or
Start tab is DemoDestinationDestination