【发布时间】:2020-06-28 22:59:14
【问题描述】:
从 ViewPager2 的嵌套片段返回的正确方法是什么?
尽管在页面的嵌套片段中使用app:defaultNavHost="true" 和FragmentContainerView 按下后退按钮调用 Activity 的后退按钮,而不是导航回上一个片段。
【问题讨论】:
标签: android android-architecture-navigation android-viewpager2
从 ViewPager2 的嵌套片段返回的正确方法是什么?
尽管在页面的嵌套片段中使用app:defaultNavHost="true" 和FragmentContainerView 按下后退按钮调用 Activity 的后退按钮,而不是导航回上一个片段。
【问题讨论】:
标签: android android-architecture-navigation android-viewpager2
根据Create a NavHostFragment documentation,app:defaultNavHost="true" 在首次添加 Fragment 时调用 setPrimaryNavigationFragment() - setPrimaryNavigationFragment() 自动将返回按钮按下事件路由到该 Fragment。
在ViewPager2 中,负责创建和添加片段的是 ViewPager2。由于 Fragment 层次结构的每一层都需要是主导航片段,通过 XML 添加子片段仍然不能解决缺失的链接:ViewPager2 中的 Fragment 需要是主导航片段。
因此,当片段成为活动片段时,您需要挂钩回调并调用setPrimaryNavigationFragment()。 ViewPager2 1.1.0-alpha01 在 FragmentTransactionCallback 中添加了这个 API,特别是 onFragmentMaxLifecyclePreUpdated(),每当 Fragment 的生命周期状态发生变化时都会调用它:当它更改为 RESUMED 时,该 Fragment 现在是活动的 Fragment 并且应该成为onPost回调的一部分的主要导航片段。
private class Adapter(parentFragment: Fragment) : FragmentStateAdapter(parentFragment) {
init {
// Add a FragmentTransactionCallback to handle changing
// the primary navigation fragment
registerFragmentTransactionCallback(object : FragmentTransactionCallback() {
override fun onFragmentMaxLifecyclePreUpdated(
fragment: Fragment,
maxLifecycleState: Lifecycle.State
) = if (maxLifecycleState == Lifecycle.State.RESUMED) {
// This fragment is becoming the active Fragment - set it to
// the primary navigation fragment in the OnPostEventListener
OnPostEventListener {
fragment.parentFragmentManager.commitNow {
setPrimaryNavigationFragment(fragment)
}
}
} else {
super.onFragmentMaxLifecyclePreUpdated(fragment, maxLifecycleState)
}
})
}
// The rest of your FragmentStateAdapter...
}
【讨论】:
FragmentStateAdapter,我不得不将它们放到NavHostFragments。
app:defaultNavHost="true"in xml 则有效,否则无效。此外,当 ViewPager2 本身位于 NavHostFragment 中时,您应该将父级和页面 NavHostFragments 的默认导航设置为 true。
您需要覆盖父活动的 onBackPressed 逻辑,您需要使用https://developer.android.com/reference/androidx/navigation/NavController#popBackStack() 在嵌套片段的导航图中向上导航。
【讨论】:
这是@ianhanniballake 答案的 Java 版本(是的,我是一个 luddite,因为我还没有使用 kotlin——在我学习其他任何东西之前,我需要先彻底了解 java)。 我还没有对此进行单元测试,但它“有效”...
public class ViewPagerAdapter extends FragmentStateAdapter {
public ViewPagerAdapter(@NonNull FragmentManager fragmentManager,
@NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
registerFragmentTransactionCallback(new FragmentTransactionCallback() {
@NonNull
@Override
public OnPostEventListener onFragmentMaxLifecyclePreUpdated(@NonNull Fragment fragmentArg,
@NonNull Lifecycle.State maxLifecycleState) {
if (maxLifecycleState == Lifecycle.State.RESUMED) {
return () -> fragmentArg.getParentFragmentManager().beginTransaction()
.setPrimaryNavigationFragment(fragmentArg).commitNow();
} else {
return super.onFragmentMaxLifecyclePreUpdated(fragmentArg, maxLifecycleState);
}
}
});
}
// remainder of your FragmentStateAdapter here
}
【讨论】: