将Android片段移动到不同的容器无法更改片段的容器ID

Mat*_*ieu 8 android viewgroup android-fragments fragmenttransaction

以下是我希望我的应用程序在平板电脑上执行的操作.Fragment(0)有一些菜单会显示片段(1)...(n),如下所示:

-----------------
|   |   |   |   |
|   |   |   |   |
|(0)| X | X | X |
|   |   |   |   |
|   |   |   |   |
-----------------
 becomes
-----------------
|   |   |   |   |
|   |   |   |   |
|(0)|(1)| X | X |
|   |   |   |   |
|   |   |   |   |
-----------------
 and then
-----------------
|   |   |   |   |
|   |   |   |   |
|(0)|(2)|(1)| X |
|   |   |   |   |
|   |   |   |   |
-----------------
 etc... 
Run Code Online (Sandbox Code Playgroud)

Fragment0从不移动,其他移动到右边.离开边缘的碎片将被破坏.

所以我用一个水平的LinearLayout设置我的XML布局,并包含4个带有正确ID的FrameLayout(fragment0 ... fragment3)

我可以实例化并显示fragment0然后显示fragment1,但是我无法将它移到右边,我得到:

ERROR/AndroidRuntime(343): FATAL EXCEPTION: main
java.lang.IllegalStateException: Can't change container ID of fragment ...
Run Code Online (Sandbox Code Playgroud)

我发现的唯一相关问题是这一个那个,尝试了所有不同的解决方案,没有运气.

尝试FragmentTransaction.remove()接着.add(),尝试.replace(),尝试不同的顺序,并中途进行(甚至尝试按照某人建议的两次),试图打电话addToBackStack()......仍然没有运气.

问题是是否可以使用FragmentTransaction移动这样的片段.如果是的话,我做错了什么(和奖金,是否可以设置动画?).如果不是,那么实施这个的正确方法是什么?

请注意,我不想每次都重新实例化片段(每个片段在Web上进行一些可能需要一些时间的查询).可以将所有数据提取回活动以重新创建一个,但如果可能,我宁愿不这样做......

Pav*_*aju 22

可以使用remove()函数更改片段的容器.

这里的问题是commit().它是一个异步调用,并将其安排在主线程上.因此,FragmentManager在将其添加到其他容器之前,请立即强制执行此操作.

为此,我们将不得不使用executePendingTransactions()功能.调用此尝试后,将片段添加到新容器中.

文档:executePendingTransactions()

代码示例:

FragmentManager fManager = getSupportFragmentManager();
FragGroups fragGroups = (FragGroups) fManager.findFragmentByTag("groups");
if (fragGroups != null) {
     fManager.beginTransaction().remove(fragGroups).commit();
     fManager.executePendingTransactions();
} else {
     fragGroups = new FragGroups();
}
if (mTwoPane) {
    fManager.beginTransaction().replace(R.id.fragment_container_groups, fragGroups, "groups").commit();
} else {
    fManager.beginTransaction().replace(R.id.fragment_container, fragGroups, "groups").commit();
}
Run Code Online (Sandbox Code Playgroud)

请享用.欢迎反馈

编辑

我想在这里补充一点.因为我有同样的问题,遇到了这个线程并应用了建议的更改.问题仍然存在.然后我查看了解决我的问题的这个线程的最后一条评论:addToBackStack()在提交事务时删除方法或者如果你故意使用它,在将它添加到另一个容器之前从后栈中删除片段.希望它对未来的读者有所帮助.

  • Pavan .....我甚至都不认识你....你甚至不认识我......但我对你有一些认真的爱,我的朋友. (2认同)
  • 此解决方案的问题是无法将第一个事务添加到后台堆栈.这样做会导致原始错误"无法更改容器ID"再次出现. (2认同)

Luk*_*rog 3

我不知道这是否正是您想要的,但我针对您的问题做了一个小样本。基本上,您将使用布局文件进行正确的移动,为每个移动片段提供一个包装容器。代码示例对于答案来说有点太大,因此我将其发布到您可以在此处找到的要点中。在该示例中,按每个 的ListFragment项目(片段 1 -> 片段 2 -> 片段 3)来查看行为。