将Android片段移动到不同的容器无法更改片段的容器ID
Posted
技术标签:
【中文标题】将Android片段移动到不同的容器无法更改片段的容器ID【英文标题】:move Android fragment to a different container Can't change container ID of fragment 【发布时间】:2012-11-16 02:40:44 【问题描述】:这是我希望我的应用程序在平板电脑上执行的操作。 片段 (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 one 和that one,尝试了所有提供的不同解决方案,但没有成功。
尝试了FragmentTransaction.remove()
,然后是.add()
,尝试了.replace()
,以不同的顺序尝试了它们并在中途提交(甚至尝试按照某人的建议提交两次),尝试调用addToBackStack()
...还是没有运气。
问题是是否可以像这样使用 FragmentTransaction 移动片段。如果是的话,我做错了什么(还有奖金,是否可以制作动画?)。如果不是,那么实现这一点的正确方法是什么?
请注意,我不想每次都重新实例化片段(每个片段都会在网络上执行一些可能需要一些时间的查询)。可以将所有数据提取回活动以重新创建一个,但如果可能的话我宁愿不这样做......
【问题讨论】:
【参考方案1】:是的,可以使用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();
享受。欢迎反馈
编辑
我想在这里补充一点。由于我有同样的问题,遇到了这个线程并应用了建议的更改。问题仍然存在。然后我查看了该线程的最后一条评论,解决了我的问题:在提交事务时删除 addToBackStack()
方法,或者如果您有意使用它,请在将片段添加到另一个容器之前从返回堆栈中删除片段。希望对以后的读者有所帮助。
【讨论】:
优秀的答案!可能不是最初的问题所要寻找的,但我发现它非常有用。 Pavan ......我什至不认识你......你甚至不认识我......但我对你有一些真诚的爱,我的朋友。跨度> @TomR 我很高兴你发现它有用:) 不错。我也想做同样的事情:D 这个方案的问题是无法将第一笔交易添加到后台堆栈。这样做会导致原来的错误“无法更改容器 ID”再次出现。【参考方案2】:我不知道这是否正是您想要的,但我针对您的问题做了一个小样本。基本上,您将使用布局文件进行正确的移位,每个移位片段都有一个包装容器。代码示例对于答案来说有点大,所以我已将其发布到a gist that you can find here。在该示例中,按下 ListFragment
的每个项目(片段 1 -> 片段 2 -> 片段 3)以查看行为。
【讨论】:
它不符合我的要求,但我正在尝试更改您的代码来做到这一点...如果可以的话,我会发布它... 能够做我需要的...无法弄清楚如何将我的更改推送到您创建的要点,所以我把它放在那里:gist.github.com/4166640 对不起。这是一个错字吗,应该是LinearLayout
而不是frag_fragaccordion.xml
中的RelativeLayout
?
@midnite 你为什么这么问?两个示例都在该布局文件中使用RelativeLayout
。
我的意思是在 @Matthieu 的例子中,第 33 行 LinearLayout main_linear = (LinearLayout) getActivity().findViewById(R.id.main_linear);
对我来说很奇怪。以上是关于将Android片段移动到不同的容器无法更改片段的容器ID的主要内容,如果未能解决你的问题,请参考以下文章