使用底部导航时清除碎片状态

发布于 2025-01-25 21:30:03 字数 714 浏览 5 评论 0 原文

我们已经在此处所述实施了底部导航:

我们使用的是导航版本2.4.1,该版本支持包装盒的多个背包。这样可以节省碎片状态,从而从主片段导航a - > b - > c - > b使用底部NAV,返回后保存片段B的状态B。这是预期的和要求的行为。

但是,对于我们底部NAV菜单中的片段之一,我希望有可能不保存状态。这是由于使用对讲时导航时某种令人困惑的行为。导航框架中有没有办法设置标志以不为单个片段保存状态?或其他任何方法可以通过在片段ondestroy/onResume或类似的片段中重置UI元素来“手动”进行编程清除保存的拯救状态?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

一束光,穿透我孤独的魂 2025-02-01 21:30:03

我所做的只是使用相同的 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 }) {
                        [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
                        }
                    }
                }
            })
    }

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
                        }
                    }
                }
            })
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文