x-ray x-ray - 1 month ago 15
Android Question

Replaced fragment still visible behind new fragment

I try to implement an activity which can load different fragments into one container view element. I follow the Building a Flexible UI Training. Problem: When replacing a fragment, I can still see the replaced fragment in the background.

I see that my question has already been asked numerous times. However all the answers I found seem to be just a workaround (setting the background-color of fragments) or do not apply.

Here is what I have setup so far:

The activity's XML layout contains one FrameLayout as a container for the fragments:

<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />


The id
fragment_container
is used nowhere else in the project.

The complete XML layout of the first fragment:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="First Fragment" />


The complete XML layout of the second fragment:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#ff0000"
android:text="Fragment Second" />


The class file of the first fragment looks like this (class for second fragment analogous):

public class FirstFragment extends Fragment {

public FirstFragment() {}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_first, container, false);
}

}


In the activity's onCreate method I load the first fragment:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

// load first fragment
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, new FirstFragment())
.commit();
}
}


When selecting a menu item I try to replace the first fragment with the second fragment with this code in the activity's
onOptionsItemSelected
method:

getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new SecondFragment())
.addToBackStack(null) // <-- does not make any difference if left out
.commit();


The result is that the text "Fragment Second" is printed in red above the text "First Fragment".

What is the "right way" (i.e. not just setting a background-color) to fix this problem?

Answer

I noticed this in onCreate:

        getSupportFragmentManager()

and this in onOptionsItemSelected:

        getFragmentManager()

There are actually both versions of the FragmentManager in AppCompatActivity and they know nothing about each other. So when you tell android.app.FragmentManager to replace a fragment that was added by android.support.v4.app.FragmentManager, it doesn't know anything about a FirstFragment so the operation acts more like an add than a replace.

I've made this mistake more than once. You'll need to comb through your code and make sure you are consistent about using the support class vs. the regular class.

Comments