24

我在从后台堆栈中删除特定片段时遇到问题。我的场景是这样的。Fragment-1 被 Fragment-2 替换,然后 Fragment-2 被 Fragment-3 替换。

调用顺序;片段 1--> 片段 2--> 片段 3。

当 Fragment-3 在屏幕上然后单击后退按钮时,我想去

Fragment-1。这意味着我想从后堆栈中删除 Fragment-2。

这个怎么做 ?

4

6 回答 6

28

在后台你没有Fragments,但是FragmentTransactions。当您popBackStack()再次应用事务时,但向后。这意味着(假设你addToBackStackTrace(null)每次)在你的后台你有

1->2
2->3

如果您不将第二笔交易添加到后台堆栈,则结果是您的后台堆栈只是

1->2

因此按下后退按钮将导致执行2->1,由于片段 2 不存在而导致错误(您在片段 3 上)。
最简单的解决方案是在从 2 到 3 之前弹出 backstack

//from fragment-2:
getFragmentManager().popBackStack();
getFragmentManager().beginTransaction()
   .replace(R.id.container, fragment3)
   .addToBackStack(null)
   .commit();

我在这里做的是:从片段 2 我回到片段 1,然后直接到片段 3。这样后退按钮将再次将我从 3 带到 1。

于 2015-07-03T05:24:26.590 回答
10

我的情况与您的情况非常相似,我的解决方案只是检查我拥有的 backStack 交易量。

如果交易超过 0,那么我会立即弹出它,以便在按下时跳过它。

if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
        getSupportFragmentManager().popBackStackImmediate();
}
...
fragmentTransaction.replace(R.id.main_fragment, newFrag, MAIN_FRAGMENT_TAG);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.commit();

这将成功:

  • A -> B(后按)-> 返回 A

  • A -> B -> C(后按)-> 返回 A

我看到的唯一缺点是在转到片段 C 之前显示片段 A 的快速闪烁。

于 2017-01-03T02:47:55.577 回答
6

如果您在同一个活动中添加/启动所有三个片段,而不是add(), 使用replace()(替换Fragment2Fragment3)。该replace方法在添加新片段之前从 backstack 中删除当前片段。如果您Fragment3从不同的活动启动,因此您不能使用,请在开始新活动(添加 )之前从 backstackreplace()中删除:Fragment2Fragment3

// in Fragment2, before adding Fragment3:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
               .remove(this) // "this" refers to current instance of Fragment2
               .commit();
fragmentManager.popBackStack();
// now go ahead and launch (add) fragment3
// if fragment3 is launched from a different activity, 
// start that activity instead
fragmentManager.beginTransaction()
               .add(R.id.a_container_view_in_activity, new Fragment3(),
                    Fargment3.FRAGMENT3_ID)
               .commit();
于 2016-05-23T17:25:10.173 回答
5

片段 A ->片段 B的代码:

在 Fragments的BackStack添加Fragment A

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout_container, new fragmentB());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

片段 B ->片段 C的代码:

不要在 Fragments的BackStack中添加Fragment B

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout_container, new fragmentC());
fragmentTransaction.commit();

它将以这种方式工作:A -> B -> C并且在返回 C-> A时除外。

希望它会帮助你。

于 2015-07-04T05:01:41.000 回答
2

FragmentTransaction您可以使用FragmentManagerpop 方法从 backstack添加到 back 状态并从 backstack 中删除:

FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove(myFrag);
trans.commit();
manager.popBackStack();

或者

简单地说,您可以跳过将片段添加到片段堆栈中,这样当您从片段堆栈中返回时,Fragment-3它将返回到Fragment-1

更新 :

要禁用动画,您需要覆盖该onCreateAnimation方法...

@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
    if (disableAnim) {
        Animation a = new Animation() {};
        a.setDuration(0);
        return a;
    }
    return super.onCreateAnimation(transit, enter, nextAnim);
}
于 2015-07-03T05:11:59.233 回答
2
   for (int i = 0; i < mFragmentManager.getBackStackEntryCount(); i++) {
        currentFragment = mFragmentManager.getFragments().get(i);
        if (!(currentFragment instanceof ParticularFragment))
            mFragmentManager.popBackStack();
        else
            break;
    }
于 2018-08-22T11:48:24.007 回答