【问题标题】:move Android fragment to a different container Can't change container ID of fragment将Android片段移动到不同的容器无法更改片段的容器ID
【发布时间】: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 onethat one,尝试了所有提供的不同解决方案,但没有成功。

尝试了FragmentTransaction.remove(),然后是.add(),尝试了.replace(),以不同的顺序尝试了它们并在中途提交(甚至尝试按照某人的建议提交两次),尝试调用addToBackStack() ...还是没有运气。

问题是是否可以像这样使用 FragmentTransaction 移动片段。如果是的话,我做错了什么(还有奖金,是否可以制作动画?)。如果不是,那么实现这一点的正确方法是什么?

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

【问题讨论】:

    标签: android android-fragments viewgroup 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); 对我来说很奇怪。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    • 2021-08-18
    • 2012-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多