Sta*_*wer 5 android android-fragments android-viewpager back-stack onbackpressed
我正在使用具有 2 页的 ViewPager。ViewPager 的第一页是 MainFragment。MainFragment 有 ViewPager 作为bottomNavigationView。每个页面都有一个FragmentContainerView,默认情况下它们分别包含 HomeFragment、CommunityFragment 和 NotificationFragment。
这是源代码,这是项目的APK。因此,您可以轻松地对其进行测试和改进。
现在,如果我在 HomeFragment 中并单击一个配置文件按钮,那么它会处理到 ProfileFragment 并从那里进行设置等等。单击后退按钮,它会一一完美地返回。但它不会与其他FragmentContainerView. 即使他们直接回到父片段。总的来说,我无法处理不同 ViewPagers 和片段之间的 backstack。
为了避免混淆,FragmentContainers我像这样进行交易
val containerId = (view?.parent as ViewGroup).id
activity?.supportFragmentManager?.beginTransaction()?.add(containerId, profileFragment)?.addToBackStack(null)?.commit()
Run Code Online (Sandbox Code Playgroud)
现在 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
}
Run Code Online (Sandbox Code Playgroud)
我检查了你的代码,问题是使用
supportFragmentManager.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE)
Run Code Online (Sandbox Code Playgroud)
如果您阅读了该标志的说明,POP_BACK_STACK_INCLUSIVE它会显示:
如果设置,并且已提供返回堆栈条目的名称或 ID,则将消耗所有匹配的条目,直到找到不匹配的条目或到达堆栈底部。否则,直到但不包括该条目的所有条目都将被删除。
所以它一次删除了多个条目。
它适用于主屏幕的原因是它从未达到这种情况。它总是出现在第一种情况:
layoutManager.findFirstCompletelyVisibleItemPosition() == 0 -> {
super.onBackPressed()
}
Run Code Online (Sandbox Code Playgroud)
这正是您的案例所需要的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
}
}
Run Code Online (Sandbox Code Playgroud)
编辑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
}
Run Code Online (Sandbox Code Playgroud)
其余的可以保持不变。尝试一下并告诉我。
| 归档时间: |
|
| 查看次数: |
155 次 |
| 最近记录: |