【问题标题】:How to replace more than one fragments with another one in the back stack?如何用后堆栈中的另一个片段替换多个片段?
【发布时间】:2016-11-22 14:09:21
【问题描述】:

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

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

编辑: 题目没有标注的重复,因为这个题目更多的是要控制几个fragment在后栈中的顺序。

【问题讨论】:

标签: android fragment-backstack fragment-transitions


【解决方案1】:

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

从管理器的片段返回堆栈中弹出最后一个片段转换。如果没有要弹出的内容,则返回 false。该函数是异步的——它将要弹出的请求排入队列,但在应用程序返回到其事件循环之前不会执行该操作。

参数

name String:如果非空,这是要查找的先前返回状态的名称;如果找到,将弹出该状态之前的所有状态。 POP_BACK_STACK_INCLUSIVE 标志可用于控制命名状态本身是否被弹出。如果为 null,则仅弹出顶部状态。

标志 int:0 或 POP_BACK_STACK_INCLUSIVE。

所以在这种情况下你:

将片段 A 添加到容器和根 backstack。给它起个名字,这样你可以在弹出时引用它。

片段 A

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

将 Fragment B 添加到容器中(替换或添加,没关系)。如果您愿意,可以使用“null”或其他名称添加到 backstack。它必须不同于“first”。

片段 B

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

像使用 Fragment B 一样添加或替换 Fragment C。

片段 C

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

使用 Fragment D 添加或替换,就像使用 Fragment B 和 C 一样。

片段 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.
    }
}

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

【讨论】:

  • 这正是我实现我想要的东西的方式。但我希望不必触及 onBackPressed()。
【解决方案2】:

片段 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() 在活动中

@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();
 }

【讨论】:

  • 但是我真的需要处理 onBackPressed() 中的东西吗?我期待在删除或添加片段时使用更干净的方式来清理后台堆栈。
【解决方案3】:

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

addToBackStack(null);

【讨论】:

  • 使内边距和外边距为 0dp
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-18
  • 1970-01-01
  • 1970-01-01
  • 2017-03-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多