片段:删除视图中的所有片段

B T*_*B T 11 android android-fragments

我面临的情况是,在我的应用程序中,我有一个单一窗格双窗格样式布局.对于每种不同的布局样式,我使用的功能可以在给定所需的屏幕时正确设置布局,而不是单独处理屏幕之间可能的每一个导航操作.

它基本上是switch应用程序switch中每个屏幕的语句,每个屏幕都有一个嵌套语句来处理每种布局样式.这就是我在代码中所说的:

protected void setupScreen() {
    switch(currentScreen) {
    case SCREEN_ONE:
        switch(currentLayout) {
        case SINGLE_PANE:
            // Perform actions to setup the screen
            break;
        case DUAL_PANE:
            // Perform actions to setup the screen
            break;
        }
        break;
    case SCREEN_TWO:
        switch(currentLayout) {
        case SINGLE_PANE:
            // Perform actions to setup the screen
            break;
        case DUAL_PANE:
            // Perform actions to setup the screen
            break;
        }
        break
    // ... etc ....
    }
}
Run Code Online (Sandbox Code Playgroud)

在我要执行设置屏幕操作的部分中,这包括以下基本三个操作:

// Create the fragments if necessary
if (screenFragment == null) {
    screenFragment = new myFragment();
}

// Remove the existing fragments from the layout views
// HOW???

// Add the fragments for this screen to the view
getSupportFragmentManager().beginTransaction().add(pane1.getId(), myFragment, "myFragment").commit();
Run Code Online (Sandbox Code Playgroud)

如你所见,我正在努力的是如何做第二步.如何你删除所有Fragment从给定的小号View没有确切知道你是想去除哪些?我找到的最接近的是FragmentTransaction.replace()哪个成功地为每个案例做了这个,但是当结果证明你用Fragment相同的片段替换了它.在这种情况下,它不会删除所有,然后添加(如文档建议),它似乎删除.这是使用兼容性库的问题还是不FragmentTransaction.replace()应该使用的方式?

无论如何,我该怎么做呢?我是否必须编写一个removeAllFragments()函数来遍历每个片段并将其分离,或者是否有办法执行"二合一" FragmentTransaction.replace()函数声称的前半部分?

cra*_*ned 19

其他答案都没有真正对我有用.这是我做的:

List<Fragment> al = getSupportFragmentManager().getFragments();
if (al == null) {
   // code that handles no existing fragments
   return;
}

for (Fragment frag : al)
{
   // To save any of the fragments, add this check.
   // A tag can be added as a third parameter to the fragment when you commit it
   if (frag == null || frag.getTag().equals("<tag-name>")) {
      continue;
   }

   getSupportFragmentManager().beginTransaction().remove(frag).commit(); 
}
Run Code Online (Sandbox Code Playgroud)

或者,如果你被迫使用它(但不推荐):

.commitAllowingStateLoss();
Run Code Online (Sandbox Code Playgroud)

此外,如果您多次从视图中删除所有片段,您可以考虑检查当前的片段是否为空isDetached()isRemoving()或者您可能获得NullPointerExceptions.

更新:现在getSupportFragmentManger().getFragments()显然隐藏了文档,但在我的代码中仍然可以正常工作.这是文档的屏幕截图:

在此输入图像描述

话虽如此,由于它是隐藏的,他们不再需要使用此方法,因此请参阅下面的更新.

更新8-4-15:如果您没有使用支持库来获取片段,很遗憾没有getFragments()可用片段,但仍有一些更不方便的选项.

  1. 给每个fragment一个tagid创建时,并遍历它们来处理每个fragment任意的.
  2. 创建一个监听器使用onAttachListener,每次fragment附加一个新的activity,你可以存储它fragment,然后遍历该数据结构,fragment根据需要处理每个.

当不使用getSupportFragmentManager(),处理交易时,您需要使用getFragmentManager().

  • 哦,我没有意识到你在谈论使用普通的`FragmentManager`,而不是`SupportFragmentManager`.你是对的; `android.app.FragmentManager`没有`getFragments()`.看到我更新的答案. (3认同)

Nic*_*ion 7

典型的机制是使用FragmentManager.findFragmentByTag().您可以使用它并将标签添加到您的片段(或id的替代品).这样您就可以确定当前正在管理的片段.然后,一旦你有一个当前片段的句柄(findFragmentByTag返回非null),你可以FragmentManager.beginTransaction()用来启动一个FrgamentTransaction并删除/添加必要的片段.以这种方式工作将允许您避免要保留的片段的"重新添加"过程.

我可能会做的是像这样的代码:(警告伪代码)

Fragment pane1 = FragmentManager.findFragmentByTag("myFragmentPane1");
Fragment pane2 = FragmentManager.findFragmentByTag("myFragmentPane2");

setupScreen(pane1, pane2);
Run Code Online (Sandbox Code Playgroud)

您还应该考虑类的子类,而不是"一个类中的所有内容".你有一个相当明显的案例,马丁福勒的替换条件与子类.否则,我担心当您添加另一个屏幕时,管理员会非常难以管理.