Android FragmentTransaction.remove无效

Android FragmentTransaction.remove无效,android,fragment,overlap,Android,Fragment,Overlap,我的要求很简单:我有一个按钮,应该用FragmentB替换FragmentA 这听起来很简单,几乎可以工作,最大的问题是旧片段没有被移除,新片段放在旧片段的前面,它们在我的布局中“生活”在一起 代码: FragmentManager fragMgr = a.getSupportFragmentManager(); Fragment currentFragment = (Fragment) fragMgr.findFragmentById(R.id.fragmentitself); if(cu

我的要求很简单:我有一个按钮,应该用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_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="2" 
    android:id="@+id/fragmentcontainer">

    <fragment
        android:id="@+id/fragmentitself"
        android:name="com.WazaBe.MyApp.FragmentA"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>
布局:

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_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="2" 
    android:id="@+id/fragmentcontainer">

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

解决方案

   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);
        }
    
    }
首先,您必须从XML中删除片段,并在其中保留空容器:

<FrameLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="2" 
    android:id="@+id/fragmentcontainer" />

然后,您需要添加来自代码的
com.WazaBe.MyApp.FragmentA
片段,即在父活动的
onCreate()

解释

   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);
        }
    
    }
这是因为您的事务处理
ViewGroup
的内容,比如说
FrameLayouts
。问题是,您只能操作从代码中添加的元素,因为从XML布局中膨胀的任何元素都被视为“只读”。因此,当您将片段直接放入XML布局中时,它将成为视图层次结构的永久部分,因为它是永久的,并且整个层次结构是“只读的”,所以无法从代码中删除


修复布局并提取片段后,不再需要调用
remove()
,只需执行
replace()

即可。如果要在视图容器(如Framelayout)中放置片段,则必须确保容器为空(只有这样才能将片段放入其中).您不能替换XML文件中写入的片段,您应该通过JAVA代码将a添加到容器中,当您不需要id时,可以用B替换它

首先,您的容器是empyt:

<FrameLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" 
android:id="@+id/fragmentcontainer">
</FrameLayout>
现在,如果要替换:

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();

如果在活动上使用片段容器,则需要选择一个默认片段ABC,即使使用ft.remove,也无法删除默认片段ABC视图


如果您想在活动启动时获得片段的空视图,请使用FrameLayout容器而不是Fragment容器。

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);
        }
    
    }

@Marcin Orlowski我在FrameLayout中有一个ListView。如何从onCreate方法添加ListView?我不能那样做。Plz帮助…不确定您真正要求的是什么,但我们在这里讨论的是片段,而ListView不是片段。如果您需要代码方面的任何帮助,您可能需要发布单独的问题。