【问题标题】:Android : Return to previous fragment on back pressAndroid:返回到上一个片段后按
【发布时间】:2014-10-10 14:30:33
【问题描述】:

我已经实现了导航抽屉,它是 Activity 的子类。我的应用程序中有很多片段。我的问题在这里

假设有 3 个片段:

Fragment_1:Fragment_2:Fragment_3

当我启动我的应用程序时,会加载 Fragment_1 当我单击 Fragment_1 上的某些组件时,我会导航到 Fragment_2 等等..

原来如此

Fragment_1 > Fragment_2 > Fragment_3

当我从 Fragment_2 按返回键时,我被导航回 Fragment_1 但是当我从 Fragment_3 按下返回键时,我会导航回 Fragment_1(而不是 Fragment_2)

我希望在我的应用程序中按后退键

Fragment_1

我使用了 Fragment、FragmentManager、FragmentTransaction 如下:

MyFragment fragment = new MyFragment();
FragmentManager fragmentManager = getFragmentManager();

fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).addToBackStack(null)commit();

我尝试在 MainActivity 中覆盖 onBackPressed() :

@Override
public void onBackPressed() {


        getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        int count = getFragmentManager().getBackStackEntryCount();
        if (count == 0)
               super.onBackPressed();
    }

【问题讨论】:

    标签: android android-fragments back-stack android-navigation


    【解决方案1】:

    将您的 Activity#onBackPressed() 方法更新为:

    @Override
    public void onBackPressed() {
        if (getFragmentManager().getBackStackEntryCount() > 0) {
            getFragmentManager().popBackStack();
        } else {
            super.onBackPressed();
        }
    }
    

    您的实现不起作用的原因是因为方法 FragmentManager#popBackStack() 是异步的,并且不会在调用后立即发生。

    来自文档:

    此函数是异步的——它将请求排入队列以弹出,但在应用程序返回其事件循环之前不会执行该操作。

    参考:http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack(java.lang.String,%20int)

    【讨论】:

    • 您的代码在某些方面有效。问题是 :: 假设我导航如下 >> Fragment_1 > Fragment_2 > Fragment_3 ,然后从导航抽屉中我再次选择 Fragment_1 并导航如下,然后按返回键,我发现以下序列 Fragment_1
    • 您正在获取此序列,因为您正在执行的每个FragmentManager 操作都通过FragmentTransaction#addToBackStack() 添加到后台堆栈。我再次阅读了您的问题,但仍然不知道您在这种情况下的期望是什么。请澄清。
    • 实际上你的代码解决了我的问题。但是如何更改以下顺序 :: Fragment_1 to Fragment_1 Fragment_2 > Fragment_3。如果您仍然不明白我的意思,那么我的问题的另一个术语是删除相同片段的冗余
    • 我猜你打算做的是避免FragmentManager 和 Back 堆栈中的重复条目,对吧?如果是这样,您可以检查Fragment 是否已经在堆栈中,方法是在您提交它时设置一个TAG,然后他们搜索它(使用FragmentManager#findFragmentByTag(String TAG),如果它不返回空值,则不调用addToBackStack()。如果它解决了您的问题,也请将我的回复标记为问题的答案。
    • 你能用简短的例子说明一下吗? (findFragmentByTag(...) 的代码)
    【解决方案2】:

    您必须按照此处的说明实现自己的 backstack 实现

    Separate Back Stack for each tab in Android using Fragments

    您可以在单击片段中的后退按钮时调用 popFragments(),并在从一个片段导航到另一个片段时调用 pushFragments()。

    简而言之,

    public void onBackPressed()
    {
        FragmentManager fm = getActivity().getSupportFragmentManager();
        fm.popBackStack();
    }
    

    【讨论】:

      【解决方案3】:

      tric 位于FragmentManager#executePendingTransactions();

      这也是我用于嵌套片段的...:

      /**
       * if there is a fragment and the back stack of this fragment is not empty,
       * then emulate 'onBackPressed' behaviour, because in default, it is not working.
       *
       * @param fm the fragment manager to which we will try to dispatch the back pressed event.
       * @return {@code true} if the onBackPressed event was consumed by a child fragment, otherwise
       */
      public static boolean dispatchOnBackPressedToFragments(FragmentManager fm) {
      
          List<Fragment> fragments = fm.getFragments();
          boolean result;
          if (fragments != null && !fragments.isEmpty()) {
              for (Fragment frag : fragments) {
                  if (frag != null && frag.isAdded() && frag.getChildFragmentManager() != null) {
                      // go to the next level of child fragments.
                      result = dispatchOnBackPressedToFragments(frag.getChildFragmentManager());
                      if (result) return true;
                  }
              }
          }
      
          // if the back stack is not empty then we pop the last transaction.
          if (fm.getBackStackEntryCount() > 0) {
              fm.popBackStack();
              fm.executePendingTransactions();
              return true;
          }
      
          return false;
      }
      

      在我的onBackPressed 中:

                      if (!FragmentUtils.dispatchOnBackPressedToFragments(fm)) {
                          // if no child fragment consumed the onBackPressed event,
                          // we execute the default behaviour.
                          super.onBackPressed();
                      }
      

      【讨论】:

      • 非常有用的答案。
      【解决方案4】:

      在您的主要活动中使用此代码更改选项卡以清除堆栈。

      int count = getFragmentManager().getBackStackEntryCount();
              if(count>0){
                  for (int i = 0; i <count; i++) {
                      getFragmentManager().popBackStack();
                  }
              }
      

      然后在你的主要活动的后退执行此操作

       int count = getFragmentManager().getBackStackEntryCount();
      
           if (count == 0) {
               super.onbackpressed();
              }
      else {
              getFragmentManager().popBackStack();
          }
       }
      

      【讨论】:

        【解决方案5】:

        这是我的工作和测试代码,这将对您有所帮助

         private static final int TIME_INTERVAL = 2000;
        private long mBackPressed;
         private void applyExit() {
            if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) {
                finish();
            } else {
                 Toast.makeText(this,"Press Again to exit",Toast.LENGTH_LONG).show();
            }
            mBackPressed = System.currentTimeMillis();
        }
        
        @Override
        public void onBackPressed() {
            fm = getSupportFragmentManager();
            if (drawer.isDrawerOpen(GravityCompat.START)) {
                drawer.closeDrawer(GravityCompat.START);
            }
            if (fm.getFragments().size() <= 1) {
                applyExit();
            } else {
                for (Fragment frag : fm.getFragments()) {
                    if (frag == null) {
                        applyExit();
                        return;
                    }
                    if (frag.isVisible()) {
                        FragmentManager childFm = frag.getChildFragmentManager();
                        if (childFm.getFragments() == null) {
                            super.onBackPressed();
                            return;
                        }
                        if (childFm.getBackStackEntryCount() > 0) {
                            childFm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                            return;
                        } else {
                            fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                            return;
                        }
                    }
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-06-08
          • 2017-08-03
          • 2021-06-17
          • 1970-01-01
          • 1970-01-01
          • 2015-08-26
          • 1970-01-01
          相关资源
          最近更新 更多