【问题标题】:Android Remove Fragment and View from BackStackAndroid 从 BackStack 中删除 Fragment 和 View
【发布时间】:2012-02-09 16:49:40
【问题描述】:

我意识到这个问题之前已经被问过,但是到目前为止之前的答案已经让我明白了。场景如下:我们有一个仪表板片段(A),它将用户引导到登录屏幕(B)。成功登录后,他们会转到列表视图 (c)。在后台我想返回 A,因为用户不需要再次看到登录屏幕。此外,在成功登录后,我们将详细信息存储在共享首选项中,并在下次自动登录 B 中,这一切都按计划进行。

我有以下 FragmentHelper 方法:

public static void goToNextFragement(Fragment fragment, int container, boolean addToBackStack, Fragment ctx)
    {
        // Create new fragment and transaction
        FragmentTransaction transaction = ctx.getSupportFragmentManager().beginTransaction();
        transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(container, fragment);

        if(addToBackStack)
            transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

在从 B 到 C 的事务中,我将布尔 addToBackStack 设置为 false,以便不调用 transaction.addToBackStack(null);。这再次运作良好,但之后是我的问题开始。

当用户按回 C 并返回到 A 时,我仍然可以在 A 的视图下看到 C 的膨胀视图。

任何帮助将不胜感激。我希望我的图表有助于保持简单。

【问题讨论】:

    标签: android android-fragments


    【解决方案1】:

    我解决了这个问题......在一行内......

    getFragmentManager().popBackStack();
    

    getSupportFragmentManager().popBackStack()
    

    这在您添加片段和维护回栈(而不是替换)时有效。

    【讨论】:

    • 当您在从 2 到 3 系统尝试显示片段 1 之前弹出回栈时。每次弹出片段编号 N 时,它都会尝试显示片段编号 (N-1)。如果您强制转到片段 3,您将在 1 个片段的 onCreateView 期间获得 NPE...
    【解决方案2】:

    f1 -> f2

    Fragment2 f2 = new Fragment2();
    this.getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.main_content,f2).addToBackStack(null).commit();
    

    这里没有什么特别之处。与片段 f2 相比,此代码将您带到片段 f3。

    f2 -> f3

    Fragment3 f3 = new Fragment3();
    getActivity().getSupportFragmentManager().popBackStack();
    getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.main_content, f3).addToBackStack(null).commit();
    

    通过阅读文档我不确定这是否可行,据说这种弹出事务方法是异步的,也许更好的方法是调用 popBackStackImmediate()。但据我所知,它在我的设备上运行良好。

    上述替代方案是:

    final FragmentActivity activity = getActivity();
    activity.getSupportFragmentManager().popBackStackImmediate();
    activity.getSupportFragmentManager().beginTransaction().replace(R.id.main_content, f3).addToBackStack(null).commit();
    

    这里实际上会在进入 f3 之前短暂地回到 f1,所以那里有一个小故障。

    这实际上是你所要做的,这个answer 也可以帮助你很多..

    【讨论】:

    • 您的解决方案非常适合我的问题,您节省了我的时间 Nepster。
    【解决方案3】:

    几种处理方法:

    1. 我的应用程序中有类似的流程,我解决它的方法是将登录片段替换为从主活动触发的 AlertDialog。 因此,在您的情况下,片段 A 显示在屏幕上,如果主要活动认为它需要显示登录对话框,它会显示 AlertDialog。这对我有用。

    2. 启用 Fragment A 后,它可以通过询问 FragmentManager 来检查 Fragment C 是否在附近。如果存在,则将其删除。

    【讨论】:

    • AlertDialogue 是要走的路。感谢您分享您的经验。
    【解决方案4】:

    第 1 步:当您在 Fragment A 并想要打开 Fragment B 时

    getFragmentManager().beginTransaction()
    .replace(android.R.id.content, new FragmentB(), FragmentB.class.getName()
    .addToBackStack(null)
    .commit();
    

    第 2 步:当您在 Fragment B 中并想要打开 Fragment C 时

    getFragmentManager().beginTransaction()
    .replace(android.R.id.content, new FragmentC(), FragmentC.class.getName()
    .disallowAddToBackStack() // << this to make Fragment B, not included in the backstack
    .commit();
    

    第 3 步:当您进入 Fragment C 并按下设备返回按钮或getFragmentManager().popBackStack(); 时,您将打开 Fragment A。

    PS:在活动中使用这个getSupportFragmentManager()。如果你在 Fragment 中使用这个getFragmentManager()

    【讨论】:

      【解决方案5】:

      不告诉FM你想把B到C的过渡加到backStack中,意思是你回击的时候,FM没有加C的记录,所以不会去掉。

      【讨论】:

      • 好的,我认为可能是这种情况,但是(冒着听起来对帮助忘恩负义的风险,我不是)这是对问题的分析,而不是解决方案。您有解决/解决此问题的任何想法吗?
      • 在我的脑海中,您可以手动删除该片段,但这可能不是最佳选择。除此之外,您还必须自己做功课。
      【解决方案6】:

      您好,我只是想分享一下我找到的优雅解决方案。

      public static void performNoBackStackTransaction(FragmentManager fragmentManager, String tag, Fragment fragment) {
      final int newBackStackLength = fragmentManager.getBackStackEntryCount() +1;
      
      fragmentManager.beginTransaction()
          .replace(R.id.content, fragment, tag)
          .addToBackStack(tag)
          .commit();
      
      fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
          int nowCount = fragmentManager.getBackStackEntryCount();
          if (newBackStackLength != nowCount) {
            // we don't really care if going back or forward. we already performed the logic here.
            fragmentManager.removeOnBackStackChangedListener(this);
      
            if ( newBackStackLength > nowCount ) { // user pressed back
              fragmentManager.popBackStackImmediate();
            }
          }
        }
      });
      }
      

      Source with explained logic.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-07
        • 2011-07-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多