Reputation: 191
I am using latest Jetpack Navigation with native support of multiple stack for bottom navigation: https://medium.com/androiddevelopers/navigation-multiple-back-stacks-6c67ba41952f and it works fine. The only limitation for me that I have to define all navigation in navigation.xml and cannot change it during the runtime.
Apparently I found out that there is an Kotlin DSL for building navigation graph programmatically: https://developer.android.com/guide/navigation/navigation-kotlin-dsl
Unfortunately I cannot find any examples of using this Kotlin DSL for bottom navigation with multiple stack.
Upvotes: 3
Views: 355
Reputation: 1
Don't forget to specify tittle = DestinationName in your menu. Title must be equal to your Destination class name
data class TopLevelRoute<T : Destination>(val route: T)
val topLevelRoutes = listOf(
TopLevelRoute(Destination.Home),
TopLevelRoute(Destination.Warehouse),
TopLevelRoute(Destination.Profile),
)
sealed class Destination {
@Serializable
data object Home : Destination()
@Serializable
data object Warehouse : Destination()
@Serializable
data class ProductDetail(val id: Int) : Destination()
@Serializable
data class ProductManage(val id: Int? = null) : Destination()
@Serializable
data object Profile : Destination()
companion object {
inline fun <reified T: Destination> from(savedStateHandle: SavedStateHandle): T = savedStateHandle.toRoute<T>()
}
}
fun NavigationBarView.setupWithNavController(
navController: NavController,
fragmentContainer: FragmentContainerView
) {
navController.addOnDestinationChangedListener { _, destination, _ ->
when {
destination.hasRoute(Destination.ProductDetail::class) -> {
hideNavigationBarWithAnimation(this, fragmentContainer)
}
else -> {
showNavigationBarWithAnimation(this, fragmentContainer)
}
}
val matchingRoute = topLevelRoutes.find { destination.hasRoute(it.route::class) }
if (matchingRoute != null) {
menu.findItemByTitle(matchingRoute.route::class.simpleName)?.isChecked = true
}
}
setOnItemSelectedListener { item ->
val selectedRoute = topLevelRoutes.find { it.route::class.simpleName == item.title }
if (selectedRoute != null) {
val isSelected =
navController.currentDestination?.hasRoute(selectedRoute.route::class) == true
if (!isSelected) {
navController.navigate(selectedRoute.route) {
popUpTo(navController.graph.startDestinationId) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
return@setOnItemSelectedListener true
}
false
}
}
private fun Menu.findItemByTitle(title: String?): MenuItem? {
for (i in 0 until size()) {
val item = getItem(i)
if (item.title == title) {
return item
}
}
return null
}
Upvotes: 0