x-ray
x-ray

Reputation: 3329

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?

Upvotes: 1

Views: 3846

Answers (1)

kris larson
kris larson

Reputation: 30985

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.

Upvotes: 3

Related Questions