FragmentTransaction.remove has no effect

Waza_Be picture Waza_Be · Nov 10, 2012 · Viewed 9.5k times · Source

My requirement is quite simple: I have a button that should replace a FragmentA by FragmentB.

This sounds easy and nearly work, the big problem is that the old fragment is not removed and the new placed on the front of the old one and they are "living" together in my layout.

enter image description here

The Code:

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

The Layout:

<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>

Answer

Marcin Orlowski picture Marcin Orlowski · Nov 10, 2012

Solution

First, you have to remove your fragment from XML and just keep empty container there:

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

Then you need to add your com.WazaBe.MyApp.FragmentA fragment from code, i.e. in onCreate() of your parent Activity.

Explanation

It is because your transactions manipulate content of ViewGroup such as said FrameLayouts. The catch is, that you can only manipulate elements you added from code as whatever is inflated from XML layout is considered "read-only". So when you put your Fragment directly into your XML layout, then it becomes permanent part of the view hierarchy and because it is permanent and the whole hierarchy is "read-only" it cannot be removed from code.

Once you get your layout fixed and Fragment extracted, the remove() call is no longer needed - it will suffice to just do replace().