'Clear state for fragment when using bottom navigation
We have implemented bottom navigation as described here:
https://developer.android.com/guide/navigation/navigation-ui#bottom_navigation
https://medium.com/androiddevelopers/navigation-multiple-back-stacks-6c67ba41952f
We are using navigation version 2.4.1, which supports multiple backstacks out of the box. This saves fragment state so that in navigating from main fragment A -> B -> C -> B using the bottomnav, state of fragment B is saved and restored upon return. This is as intended and much requested behaviour.
However, for one of the fragments in our bottomnav menu, I would like the possibility to NOT save the state. This is due to some confusing behaviour when navigating using talkback. Is there a way in the navigation framework to set a flag to not save state for a single fragment? Or any other way to programmatically clear savedstate without actually doing so "manually" by resetting the UI elements in fragment onDestroy/onResume or similar?
Solution 1:[1]
What I did was just use the same androidx.navigation.ui.NavigationUI.setupWithNavController logic but change the saveState and other logic specific to my use case. You could apply this when navigating to one specific fragment.
        this.findViewById<BottomNavigationView>(R.id.bottom_navigation).apply {
        setOnItemSelectedListener { item ->
            val builder = NavOptions.Builder().setLaunchSingleTop(true)
            val destinationId = item.itemId
            item.isChecked = true
            if (
                navController.currentDestination!!.parent!!.findNode(item.itemId)
                        is ActivityNavigator.Destination
            ) {
                builder.setEnterAnim(R.anim.nav_default_enter_anim)
                    .setExitAnim(R.anim.nav_default_exit_anim)
                    .setPopEnterAnim(R.anim.nav_default_pop_enter_anim)
                    .setPopExitAnim(R.anim.nav_default_pop_exit_anim)
            } else {
                builder.setEnterAnim(R.animator.nav_default_enter_anim)
                    .setExitAnim(R.animator.nav_default_exit_anim)
                    .setPopEnterAnim(R.animator.nav_default_pop_enter_anim)
                    .setPopExitAnim(R.animator.nav_default_pop_exit_anim)
            }
            if (item.order and Menu.CATEGORY_SECONDARY == 0) {
                builder.setPopUpTo(
                    navController.graph.findStartDestination().id,
                    inclusive = false,
                    saveState = false
                )
            }
            val options = builder.build()
            return@setOnItemSelectedListener try {
                navController.navigate(destinationId, null, options)
                // Return true only if the destination we've navigated to matches the MenuItem
                (navController.currentDestination?.id ?: false) == destinationId
            } catch (e: IllegalArgumentException) {
                false
            }
        }
        // Do nothing on reselect
        setOnItemReselectedListener {}
        val weakReference = WeakReference(this)
        navController.addOnDestinationChangedListener(
            object : NavController.OnDestinationChangedListener {
                override fun onDestinationChanged(
                    controller: NavController,
                    destination: NavDestination,
                    arguments: Bundle?
                ) {
                    // Hide BottomNavigationView from top level fragments
                    if (topLevelDestinations.any { it == destination.id }) {
                        [email protected] = View.VISIBLE
                    } else [email protected] = View.GONE
                    // Highlight item in BottomNavigationView
                    val view = weakReference.get()
                    if (view == null) {
                        navController.removeOnDestinationChangedListener(this)
                        return
                    }
                    view.menu.forEach { item ->
                        if (destination.id == item.itemId) {
                            item.isChecked = true
                        }
                    }
                }
            })
    }
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | MakinTosH | 
