如何在后台堆栈中用另一个片段替换多个片段?

How to replace more than one fragments with another one in the back stack?

我在后台堆栈中有以下片段A、B、C。然后我想添加片段 D,但是在后面的堆栈中我想放 A 和 D 而不是 A, B , C, D。 问题是当我尝试使用 transaction.remove() 删除 B 和 C 时,backStackEntryCount 仍然是旧的,它在按下后退时会出现空白屏幕。有办法处理吗?

当我使用popBackStack()时,片段A然后片段D,这会产生奇怪的动画效果。

编辑: 题目没有标注的重复,因为这道题更多的是控制返回栈中几个分片的顺序

片段A

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, FragmentA, "FragmentA");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

片段 B

fragmentTransaction.replace(R.id.fragment_container, FragmentB, "FragmentB");

片段 C

 fragmentTransaction.replace(R.id.fragment_container, FragmentC, "FragmentC");

片段 D

 fragmentTransaction.replace(R.id.fragment_container, FragmentD, "FragmentD");

现在你的 onBackPressed() 在 activity

@Override
public void onBackPressed() {


int lastStack = getSupportFragmentManager().getBackStackEntryCount();
try {
    //If the last fragment was named/tagged "three"
    if (getSupportFragmentManager().getFragments().get(lastStack).getTag().toString()=="FragmentD"){

        getSupportFragmentManager().popBackStackImmediate();//skip c
        getSupportFragmentManager().popBackStackImmediate();//skip B
         Fragment fragment = getSupportFragmentManager().findFragmentByTag("FragmentA");
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.fragment_container, fragment);
        transaction.commit();
        return;
    }
} catch (Exception e) {

    e.printStackTrace();
}

super.onBackPressed();
 }

为每个片段制作fragment_container并继续替换最新片段的fragment_container.. 别忘了:

addToBackStack(null);

添加到 Backstack 时,您可以包含一个名称,以便在您处于特定状态时将 backstack 弹出到该名称。基于 FragmentManager#popBackStack(string, int); 的文档:

Pop the last fragment transition from the manager's fragment back stack. If there is nothing to pop, false is returned. This function is asynchronous -- it enqueues the request to pop, but the action will not be performed until the application returns to its event loop.

Parameters

name String: If non-null, this is the name of a previous back state to look for; if found, all states up to that state will be popped. The POP_BACK_STACK_INCLUSIVE flag can be used to control whether the named state itself is popped. If null, only the top state is popped.

flags int: Either 0 or POP_BACK_STACK_INCLUSIVE.

所以在这种情况下你:

将片段 A 添加到容器和根后台堆栈。给它起个名字,以便弹出时可以引用它。

片段 A:

FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, FragmentA, "FragmentA")
.addToBackStack("first")
.commit();

将片段 B 添加到容器中(替换或添加,无所谓)。如果您愿意,可以使用“null”或其他名称添加到后台堆栈。它必须不同于“first”。

片段 B:

FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, FragmentB, "FragmentB")
.addToBackStack(null)
.commit();

像使用片段 B 一样添加或替换为片段 C。

片段 C:

FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, FragmentC, "FragmentC")
.addToBackStack(null)
.commit();

像使用片段 B 和 C 一样添加或替换为片段 D。

片段 D:

FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, FragmentD, "FragmentD")
.addToBackStack(null)
.commit();

然后,在 onBackPressed() 中,您首先检查“FragmentD”是否在堆栈中。如果是,则一直弹出到根(在本例中为“第一”)。如果没有,请像往常一样处理后压。

@Override
public void onBackPressed() {
    FragmentManager fm = getFragmentManager();
    if (fm.findFragmentByTag("FragmentD") != null) {
       fm.popBackStack("first", 0); // Pops everything up to "first" 
    } else {
       super.onBackPressed(); // Pops backstack like normal or leaves App if at base.
    }
}

这应该做的是让您的用户在片段 A、B 或 C 中按下后退按钮时“返回”。然后当他们最终进入片段 D 时,它会一直弹出到 A.