【问题标题】:How to navigate back from fragments inside NavHostFragment of ViewPager2?如何从 ViewPager2 的 NavHostFragment 内的片段导航回来?
【发布时间】:2020-06-28 22:59:14
【问题描述】:

从 ViewPager2 的嵌套片段返回的正确方法是什么?

尽管在页面的嵌套片段中使用app:defaultNavHost="true"FragmentContainerView 按下后退按钮调用 Activity 的后退按钮,而不是导航回上一个片段。

【问题讨论】:

    标签: android android-architecture-navigation android-viewpager2


    【解决方案1】:

    根据Create a NavHostFragment documentationapp:defaultNavHost="true" 在首次添加 Fragment 时调用 setPrimaryNavigationFragment() - setPrimaryNavigationFragment() 自动将返回按钮按下事件路由到该 Fragment。

    ViewPager2 中,负责创建和添加片段的是 ViewPager2。由于 Fragment 层次结构的每一层都需要是主导航片段,通过 XML 添加子片段仍然不能解决缺失的链接:ViewPager2 中的 Fragment 需要是主导航片段。

    因此,当片段成为活动片段时,您需要挂钩回调并调用setPrimaryNavigationFragment()ViewPager2 1.1.0-alpha01FragmentTransactionCallback 中添加了这个 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
    • 如果 NavHostFragment 设置为 app:defaultNavHost="true"in xml 则有效,否则无效。此外,当 ViewPager2 本身位于 NavHostFragment 中时,您应该将父级和页面 NavHostFragments 的默认导航设置为 true。
    【解决方案2】:

    您需要覆盖父活动的 onBackPressed 逻辑,您需要使用https://developer.android.com/reference/androidx/navigation/NavController#popBackStack() 在嵌套片段的导航图中向上导航。

    【讨论】:

      【解决方案3】:

      这是@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
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-01
        • 2020-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-02
        相关资源
        最近更新 更多