FragmentTransaction.remove 没有效果

Posted

技术标签:

【中文标题】FragmentTransaction.remove 没有效果【英文标题】:FragmentTransaction.remove has no effect 【发布时间】:2012-10-30 15:43:09 【问题描述】:

我的要求很简单:我有一个按钮应该用 FragmentB 替换 FragmentA。

这听起来很简单,几乎可以工作,最大的问题是旧片段没有被删除,新片段放在旧片段的前面,它们在我的布局中“生活”在一起。

守则:

FragmentManager fragMgr = a.getSupportFragmentManager();
Fragment currentFragment = (Fragment) fragMgr.findFragmentById(R.id.fragmentitself);

if(currentFragment!=null)

     FragmentTransaction fragTrans = fragMgr.beginTransaction();
     fragTrans.remove(currentFragment);

     FragmentB newFragment = new FragmentB();
     fragTrans.replace(R.id.fragmentcontainer, newFragment);
     // I have also tried with R.id.fragmentitself
     fragTrans.addToBackStack(null);
     fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
     fragTrans.commit();

布局:

<FrameLayout
    android:layout_
    android:layout_
    android:layout_weight="2" 
    android:id="@+id/fragmentcontainer">

    <fragment
        android:id="@+id/fragmentitself"
        android:name="com.WazaBe.MyApp.FragmentA"
        android:layout_
        android:layout_ />
</FrameLayout>

【问题讨论】:

【参考方案1】:

解决方案

首先,您必须从 XML 中删除您的片段,并在其中保留空容器:

<FrameLayout
    android:layout_
    android:layout_
    android:layout_weight="2" 
    android:id="@+id/fragmentcontainer" />

然后您需要从代码中添加您的 com.WazaBe.MyApp.FragmentA 片段,即在您的父 Activity 的 onCreate() 中。

说明

这是因为您的交易操纵了ViewGroup 的内容,例如FrameLayouts。问题是,您只能操作从代码中添加的元素,因为从 XML 布局膨胀的任何内容都被视为“只读”。因此,当您将 Fragment 直接放入 XML 布局时,它会成为视图层次结构的 永久 一部分,并且因为它是永久的并且整个层次结构是“只读的”,所以它不能从代码中删除。

一旦您修复了布局并提取了 Fragment,就不再需要调用 remove() - 只需执行 replace() 就足够了。

【讨论】:

@Marcin Orlowski 我在 FrameLayout 中有一个 ListView。如何从 onCreate 方法添加 ListView?我不能那样做。请帮助... 不确定你真正问的是什么,但我们在这里讨论片段,ListView 不是片段。如果您需要有关代码的任何帮助,您可能需要发布单独的问题。【参考方案2】:

如果你想在一个视图容器中放置一个Fragment(比如一个Framelayout),你必须确保你的容器是空的(只有这样你才能在里面放一个Fragment)。你不能替换一个用XML写的Fragment文件,你应该通过JAVA代码将A添加到容器中,当你不需要id时,你可以将它替换为B;

首先,你的容器是空的:

<FrameLayout
android:layout_
android:layout_
android:layout_weight="2" 
android:id="@+id/fragmentcontainer">
</FrameLayout>

好的,你把FragmentA放进去:

 FragmentTransaction fragTrans = fragMgr.beginTransaction();
 fragTrans.remove(currentFragment);
 FragmentA fragA= new FragmentA();
 fragTrans.add(R.id.fragmentcontainer, fragA).commit();

现在,如果你想替换:

FragmentTransaction fragTrans = fragMgr.beginTransaction();
 FragmentB newFragment = new FragmentB();
 fragTrans.replace(R.id.fragmentcontainer, newFragment);
 // I have also tried with R.id.fragmentitself
 fragTrans.addToBackStack(null);
 fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
 fragTrans.commit();

【讨论】:

【参考方案3】:

如果我们在activity上使用Fragment容器,它需要选择一个默认的FragmentABC,即使我们使用ft.remove,默认的FragmentABC视图也无法移除。

如果您想在 Activity 启动时看到 Fragment 的空视图,请使用 FrameLayout 容器而不是 Fragment 容器。

【讨论】:

【参考方案4】:

Kotlin 中的相同答案

   private fun showDetailView(position: Int) 
            val fragTrans: FragmentTransaction = supportFragmentManager.beginTransaction()
            val fragment: Fragment
            when (position) 
                0 -> fragment = FragmentA()
                1 -> fragment = FragmentB()
                else ->
                    fragment = FragmentC()
            
            fragTrans.replace(
                    R.id.itemDetailContainer,
                    fragment).commit()
            fragTrans.addToBackStack(null);
            fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        
    
    

【讨论】:

以上是关于FragmentTransaction.remove 没有效果的主要内容,如果未能解决你的问题,请参考以下文章