x-ray x-ray - 1 year ago 93
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 Source

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download