首先,如果这是任何线程的重复,我很抱歉,我已经搜索过,我没有发现任何与我的情况真正相似的东西,或者至少没有发现可以帮助我解决问题的东西。
基本上,我想知道在以简单干净的方式调用onBackPressed()方法时,在片段之间导航的最佳方法是什么。
我有一个调用片段的活动(我们称之为 ListFrag)。此 ListFrag 显示一个项目列表,单击该列表时,将调用包含该项目详细信息的另一个片段(我们称之为 DetailFrag)。这很简单,一切正常:ListFrag调用DetailFrag,按后退按钮将按预期向后导航。好!
但我的问题是,现在我在ListFrag和DetailFrag之间增加了一个额外的步骤。现在,ListFrag将调用另一个名为PagerFrag的片段,这将允许我们通过滑动(使用FragmentStatePagerAdapter)进行分页,一个接一个地显示多个DetailFrags。另外,我需要支持两种情况:
情况 1:用户使用智能手机,导航流将是 ListFrag> PagerFrag> DetailFrag,无论设备的方向如何。
情况2:用户使用的是平板电脑,如果它处于纵向模式,它将作为第一个情况工作,但如果它处于横向模式,它将不得不忽略 PagerFrag(我们将无法通过滑动进行分页)并在同一布局上显示 ListFrag 和 DetailFrag。
我再次做了一些工作,在所有情况下都运行良好。主要问题是向后导航时:按下后退按钮变成了一场噩梦,因为我完全不知道 FragmentManager 如何堆叠片段(或片段事务,如果我没记错的话),因为 PagerFrag 将多个 DetailFrag 添加到堆栈中(寻呼机中的上一个、当前和下一个)。我必须在onBackPressed()方法中不断检查"if(fragment is DetailFrag)",以便能够告诉应用程序下一步要去哪里。
想想这种情况:用户正在纵向模式下使用平板电脑。用户导航 ListFrag> PagerFrag> DetailFrag。然后,用户更改设备方向。我必须"杀死"寻呼机和 DetailFrag,使用其他 xml 布局(并排显示 2 个片段的布局)重新创建 ListFrag,并在那里膨胀 DetailFrag。
它正在工作,但所有这些解决方法都是丑陋的,并且实际上没有遵循最佳实践。这使得代码维护/重用非常无聊。
我使用一个视图模型来连接活动和 3 个片段,并且使用 LiveData,我设法在 UI 中正确显示信息。项目的数据不是问题,只是所有这些片段之间的向后导航。
我尝试在重新创建活动或用户导航回来时处理每种特定情况,但我不喜欢这种方法。
我目前的解决方案是这样的:
override fun onBackPressed() {
if (supportFragmentManager.backStackEntryCount == 0) {
super.onBackPressed()
} else {
if(supportFragmentManager.fragments.first() is PagerFrag ||
(!viewModel.isTwoPane)){
/* isTwoPane indicates if we will have 2 fragments side by side if it's a tablet in landscape mode */
for(frag in supportFragmentManager.fragments) {
if(frag is DetailFrag) {
supportFragmentManager
.beginTransaction()
.remove(frag)
.commit()
}
}
}
supportFragmentManager.popBackStackImmediate()
}
}
在片段的 onCreatedView() 方法中还有几行,以便在重新创建活动(方向更改)时进行处理。
因此,我希望找到一种简单的方法在片段之间向后导航,而不必检查诸如"用户是否在横向模式下使用平板电脑并且他是否正在查看DetailFrag?所以做这个,这个和那个。 我宁愿暂时避免使用新的AndroidX导航,因为我正在处理一个(有点)复杂的项目。
感谢您抽出宝贵时间,如果我需要提供更多信息/背景,请告诉我!
在对Back Stack和onBackPressed()方法中的所有实例检查进行了更多的斗争之后,我决定再次尝试AndroidX导航架构,就像JDevoloper在评论中建议的那样,结果证明它运行良好。这确实是一个很好的解决方案。我在更改设备方向时仍然在使用 ViewPager 和处理导航时遇到一些问题,但现在一切都解决了并按预期工作。谢谢你的帮助!