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

时间:2012-11-28 09:30:09

标签: android android-fragments viewgroup fragmenttransaction

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

-----------------
|   |   |   |   |
|   |   |   |   |
|(0)| X | X | X |
|   |   |   |   |
|   |   |   |   |
-----------------
 becomes
-----------------
|   |   |   |   |
|   |   |   |   |
|(0)|(1)| X | X |
|   |   |   |   |
|   |   |   |   |
-----------------
 and then
-----------------
|   |   |   |   |
|   |   |   |   |
|(0)|(2)|(1)| X |
|   |   |   |   |
|   |   |   |   |
-----------------
 etc... 

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 ...

我发现的唯一相关问题是this onethat one,尝试了所有不同的解决方案而没有运气。

尝试FragmentTransaction.remove()后跟.add(),尝试.replace(),尝试使用不同的命令并中途执行(甚至尝试按照某人的建议提交两次),试图调用addToBackStack() ......仍然没有运气。

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

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

2 个答案:

答案 0 :(得分:21)

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

这里的问题是commit()。它是一个异步调用,并将其安排在主线程上。因此,在将FragmentManager添加到其他容器之前,强制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(); } 功能。调用此尝试后,将片段添加到新容器中。

文档:executePendingTransactions()

代码示例:

addToBackStack()

享受。欢迎反馈

修改

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

答案 1 :(得分:3)

我不知道这是否是您想要的,但我对您的问题做了一些示例。基本上你将使用布局文件进行正确的移位,为每个移动片段都有一个包装容器。代码示例对于答案来说有点大,所以我已将其发布到a gist that you can find here。在该示例中,按下每个ListFragment项(片段1 - >片段2 - >片段3)以查看行为。