android - 如何处理片段和视图分页器之间的回栈?
问题描述
我正在使用有 2 页的 ViewPager。该 ViewPager 的第一页是 MainFragment。MainFragment 具有 ViewPager 作为bottomNavigationView
. 每个页面都有一个FragmentContainerView
,默认情况下它们分别包含 HomeFragment、CommunityFragment 和 NotificationFragment。
这是源代码,这是项目的APK。因此,您可以轻松地对其进行测试和改进。
现在,如果我在 HomeFragment 中并单击配置文件按钮,则它会处理到 ProfileFragment 并从那里进行设置等等。在点击后退按钮时,它会一一完美地返回。但它不会发生与其他相同FragmentContainerView
。即使他们直接返回到父片段。总的来说,我无法处理不同 ViewPager 和片段之间的 backstack。
为了避免FragmentContainers
我这样交易的混乱
val containerId = (view?.parent as ViewGroup).id
activity?.supportFragmentManager?.beginTransaction()?.add(containerId, profileFragment)?.addToBackStack(null)?.commit()
现在MainActivity中BackPressed()的处理就到这里了
if (view_pager_main_activity?.currentItem == 0)
{
if (view_pager_main_fragment?.currentItem == 0)
{
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view_home)
val appbarHome = findViewById<AppBarLayout>(R.id.appbar_home)
val layoutManager = recyclerView?.layoutManager as LinearLayoutManager
when {
layoutManager.findFirstCompletelyVisibleItemPosition() == 0 -> {
super.onBackPressed()
}
supportFragmentManager.backStackEntryCount != 0 -> {
supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
}
else -> {
layoutManager.scrollToPositionWithOffset(0, 0)
appbarHome.setExpanded(true)
//recyclerView.smoothScrollToPosition(0)
}
}
}
else
{
// Otherwise, select the previous step.
view_pager_main_fragment?.setCurrentItem(view_pager_main_fragment.currentItem - 1, false)
}
}
else
{
// Otherwise, select the previous step.
view_pager_main_activity?.currentItem = view_pager_main_activity.currentItem - 1
}
解决方案
我检查了你的代码,问题是使用
supportFragmentManager.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE)
如果您阅读标志的描述,POP_BACK_STACK_INCLUSIVE
它会说:
如果设置,并且提供了返回堆栈条目的名称或 ID,则将使用所有匹配的条目,直到找到不匹配的条目或到达堆栈底部。否则,将删除该条目之前但不包括该条目的所有条目。
所以它一次删除了多个条目。
它适用于主屏幕的原因是它从未达到过这种情况。它总是出现在第一种情况下:
layoutManager.findFirstCompletelyVisibleItemPosition() == 0 -> {
super.onBackPressed()
}
这正是您的案例所需要的,super.onBackPressed()
当您想一次只弹出一个片段时只需调用即可。所以你的最终代码变成了这样:
在您的 MainActivity 中onBackPressed()
override fun onBackPressed() {
if (view_pager_main_activity?.currentItem == 0) {
if (view_pager_main_fragment?.currentItem == 0) {
val recyclerView = findViewById<RecyclerView>(R.id.listRecyclerView)
val appbarHome = findViewById<AppBarLayout>(R.id.appbar_home)
val layoutManager = recyclerView?.layoutManager as LinearLayoutManager
when {
layoutManager.findFirstCompletelyVisibleItemPosition() == 0 -> {
super.onBackPressed()
}
//This is never reached. It can be removed
supportFragmentManager.backStackEntryCount != 0 -> {
supportFragmentManager.popBackStack(
null,
FragmentManager.POP_BACK_STACK_INCLUSIVE
)
}
else -> {
layoutManager.scrollToPositionWithOffset(0, 0)
appbarHome.setExpanded(true)
//recyclerView.smoothScrollToPosition(0)
}
}
} else if (supportFragmentManager.backStackEntryCount != 0) {
super.onBackPressed()
} else {
// Otherwise, select the previous step.
view_pager_main_fragment?.setCurrentItem(
view_pager_main_fragment.currentItem - 1,
false
)
}
} else if (supportFragmentManager.backStackEntryCount != 0) {
super.onBackPressed()
} else {
// Otherwise, select the previous step.
view_pager_main_activity?.currentItem = view_pager_main_activity.currentItem - 1
}
}
编辑1:来自评论
我想在底部导航选择更改时清除后台堆栈。
如果您想在更改底部导航选择更改时清除选择,那么您必须设置一个侦听器并清除您的后退堆栈,MainFragment
如下所示:
view?.bottomNavView?.setOnNavigationItemSelectedListener { item ->
//check if item is being re-selected then just return and don't do anything
if (bottomNavView.selectedItemId == item.itemId){
return@setOnNavigationItemSelectedListener false
}
//if the bottom nav item selection changes then clear the back stack of previous tab
parentFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
when (item.itemId) {
R.id.homeFragment -> viewPager2.setCurrentItem(0, false)
R.id.searchFragment -> viewPager2.setCurrentItem(1, false)
R.id.notificationsFragment -> viewPager2.setCurrentItem(2, false)
}
true
}
其余的可以保持不变。试试这个,让我知道。
推荐阅读
- python - 使用 rsplit 从字符串末尾删除某些字母的单行器?
- regex - NLTK 正则表达式解析器的输出已更改。无法解析动词后跟名词之类的短语
- reactjs - 动态链接在 react-app 的构建中不起作用
- python - 如何在python中对字符串进行子串化?
- excel - VBA:将子程序包含在条件中
- android - 插页式广告关闭后如何进行下一个活动而不是相同的活动?
- javascript - Vue JS 2:在 beforeCreate 之后停止生命周期
- java - 将 Intellij 键盘设置映射到 Visual Studio
- karate - 如何根据条件将值为 Null 的新键添加到动态响应体中
- python - 没有找到 PyJWT<3.0.0,>=2.0.1 的匹配分布