将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的主要内容,如果未能解决你的问题,请参考以下文章

无法移动到嵌套子导航组件中的父片段?

设置onclick侦听器在android中无法从一个片段移动到另一个活动[重复]

如何在 Android 中的特定片段容器中显示片段

手动设置片段的屏幕方向

Android - 如何更改导航抽屉中的片段

Android:使用 putExtra 从片段访问容器活动对象?