如何从 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

}