如何从 ViewPager2 的 NavHostFragment 内的片段导航回来?
How to navigate back from fragments inside NavHostFragment of ViewPager2?
从 ViewPager2 的嵌套片段导航回来的正确方法是什么?
尽管在页面的嵌套片段中使用 app:defaultNavHost="true"
和 FragmentContainerView
按下后退按钮调用 Activity 的后退按钮而不是导航回上一个片段。
您需要覆盖您父级 activity 的 onBackPressed 逻辑,您需要使用 https://developer.android.com/reference/androidx/navigation/NavController#popBackStack() 在嵌套片段的导航图中向上导航。
根据首次添加片段时的 Create a NavHostFragment documentation, app:defaultNavHost="true"
calls setPrimaryNavigationFragment()
- setPrimaryNavigationFragment()
会自动将后退按钮按下事件路由到该片段。
不过在 ViewPager2
中,负责创建和添加片段的是 ViewPager2。由于 Fragment 层次结构的每个级别都需要作为主导航片段,因此通过 XML 添加子片段仍然不能解决缺少的 link:ViewPager2 中的 Fragment 需要作为主导航片段.
因此,当 Fragment 成为活动 Fragment 并调用 setPrimaryNavigationFragment()
时,您需要挂钩回调。 ViewPager2 1.1.0-alpha01 adds exactly this API in the FragmentTransactionCallback
, specifically, the onFragmentMaxLifecyclePreUpdated()
,每当 Fragment 的生命周期状态发生变化时调用:当它更改为 RESUMED
时,该 Fragment 现在是活动片段,应该成为主要导航 Fragment 作为 [= 的一部分19=]回调。
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...
}
这是@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
}
从 ViewPager2 的嵌套片段导航回来的正确方法是什么?
尽管在页面的嵌套片段中使用 app:defaultNavHost="true"
和 FragmentContainerView
按下后退按钮调用 Activity 的后退按钮而不是导航回上一个片段。
您需要覆盖您父级 activity 的 onBackPressed 逻辑,您需要使用 https://developer.android.com/reference/androidx/navigation/NavController#popBackStack() 在嵌套片段的导航图中向上导航。
根据首次添加片段时的 Create a NavHostFragment documentation, app:defaultNavHost="true"
calls setPrimaryNavigationFragment()
- setPrimaryNavigationFragment()
会自动将后退按钮按下事件路由到该片段。
不过在 ViewPager2
中,负责创建和添加片段的是 ViewPager2。由于 Fragment 层次结构的每个级别都需要作为主导航片段,因此通过 XML 添加子片段仍然不能解决缺少的 link:ViewPager2 中的 Fragment 需要作为主导航片段.
因此,当 Fragment 成为活动 Fragment 并调用 setPrimaryNavigationFragment()
时,您需要挂钩回调。 ViewPager2 1.1.0-alpha01 adds exactly this API in the FragmentTransactionCallback
, specifically, the onFragmentMaxLifecyclePreUpdated()
,每当 Fragment 的生命周期状态发生变化时调用:当它更改为 RESUMED
时,该 Fragment 现在是活动片段,应该成为主要导航 Fragment 作为 [= 的一部分19=]回调。
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...
}
这是@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
}