android-fragments 使用底部导航时清除片段状态

nbnkbykc  于 2022-11-14  发布在  Android
关注(0)|答案(1)|浏览(151)

我们已经实现了底部导航,如下所述:
https://developer.android.com/guide/navigation/navigation-ui#bottom_navigation
https://medium.com/androiddevelopers/navigation-multiple-back-stacks-6c67ba41952f
我们使用的是导航版本2.4.1,它支持多个现成的backstack。这将保存片段状态,以便在使用bottomnav从主片段A -〉B -〉C -〉B导航时,片段B的状态将被保存,并在返回时恢复。这是预期的和许多请求的行为。
但是,对于底部导航菜单中的一个片段,我希望有不保存状态的可能性。这是由于使用对讲进行导航时的一些混乱行为。在导航框架中是否有一种方法可以设置一个标志,以不保存单个片段的状态?或者有任何其他方法可以通过重置片段onDestroy/中的UI元素,以编程方式清除savedstate,而无需实际“手动”执行此操作在简历或类似?

de90aj5v

de90aj5v1#

我所做的只是使用相同的androidx.navigation.ui.NavigationUI.setupWithNavController逻辑,但更改了saveState和其他特定于我的用例的逻辑。

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 }) {
                        this@apply.visibility = View.VISIBLE
                    } else this@apply.visibility = 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
                        }
                    }
                }
            })
    }

相关问题