3

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.

1
  • 2
    Where you able to find any examples for this? I am also looking for it with no luck. Commented Feb 9, 2022 at 5:08

1 Answer 1

0

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
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.