如何从ViewPager2的NavHostFragment中的片段返回?

3
什么是从ViewPager2的嵌套片段中导航回来的正确方法?
尽管在FragmentContainerView中使用了app:defaultNavHost="true",但在页面的嵌套片段中按下返回按钮会调用Activity的返回按键,而不会导航回以前的片段。
3个回答

9
根据创建NavHostFragment文档app:defaultNavHost="true"在首次添加Fragment时调用setPrimaryNavigationFragment()。因此,会自动将后退按钮事件路由到该Fragment。
但是,在ViewPager2中,它是负责创建和添加Fragment的。由于每个Fragment层级都需要成为主要导航Fragment,因此通过XML添加子Fragment仍然无法解决缺失的链接:即ViewPager2中的Fragment需要成为主要导航Fragment。
因此,您需要钩入Fragment成为活动Fragment的回调,并调用setPrimaryNavigationFragment()ViewPager2 1.1.0-alpha01FragmentTransactionCallback中增加了这个API,具体而言,就是onFragmentMaxLifecyclePreUpdated(),每当Fragment的生命周期状态被更改时都会调用:当它被更改为RESUMED时,该Fragment现在是活动Fragment,并且应该成为onPost回调的主要导航Fragment。
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中。 - Thracian
如果在xml中设置了app:defaultNavHost="true",则NavHostFragment可以正常工作,否则将无法正常工作。此外,当ViewPager2本身位于NavHostFragment中时,您应该为父级和页面NavHostFragments都设置默认导航为true。 - Thracian

1

以下是@ianhanniballake答案的Java版本(是的,我还没有使用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

}

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接