Niels
Niels

Reputation: 9394

Fragments displayed over each other

I've got an Activity with a DrawerLayout, using the guidelines from http://developer.android.com/training/implementing-navigation/nav-drawer.html.

When I click on an drawerItem, I replace the current view with the new fragment:

Fragment fragment;
Bundle args = new Bundle();    
fragment = new NewsListFragment();
args.putInt("category", position);

// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
                   .replace(R.id.content_frame, fragment)
                   .commit();        
mDrawerList.setItemChecked(position, true);

Now, sometimes the old fragment is not replaced but the new fragment is placed on top of the old one:

http://img15.imageshack.us/img15/3179/1kqj.png

Why is this, and how to solve this problem?

Relevant XML:

<!-- The main content view -->
<LinearLayout 
    android:id="@+id/rlMain"
    android:layout_width="fill_parent"
    android:orientation="vertical"
    android:layout_height="fill_parent">

    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" 
        android:layout_weight="1">
    </FrameLayout>

This only happens sometimes, and I haven't found a flow to reproduce this yet. The app doesn't support rotating, so it won't happen there.

Upvotes: 24

Views: 26042

Answers (7)

hordurh
hordurh

Reputation: 2673

Let's say that you have the root fragment A which you add to a container. Next you add fragment B and you set addToBackStack in the transaction. Lastly you add fragment C but you omit addToBackStack. Now when you press the back button you get these fragments on top of each other.

To recap:

Fragment A is added

Fragment B replaces A with addToBackStack

Fragment C replaces B without addToBackStack

Pressing back results in weird overlaid fragments where A lies on top of C.

You could solve this issue by also adding C to the backStack.

Upvotes: 0

Abdullah
Abdullah

Reputation: 393

I also encounter this issue I found that we are doing a wrong when replacing fragment

 private void changeFragment(Fragment targetFragment){

    assert getFragmentManager() != null;
    getFragmentManager()
            .beginTransaction()
            .replace(R.id.main_fragment, targetFragment, "fragment")
            .setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
            .commit();
}

this method is replace fragment as other people's code. the reason why fragments are display each other is we define different ID in framelayout in xml. we have to define framelayout IDs(old fragment and new fragment) same.

old framelayout and new framelayout ID in xml for above code should be

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

Upvotes: 0

ahmed_khan_89
ahmed_khan_89

Reputation: 2773

I run in this same problem and I see that there's already an accepted answer but these answer is not 100% right and didn't fix my problem. The proposed answer by @Niels removes the views but the fragment(s) is(are) still added. This is what I am using:

/**
 * Call this to remove all the other added fragments and keep only the current one.
 *
 * @param activity the activity to which the fragment has been attached.
 * @param fragment the fragment we want to keep.
 */
public static void removeOtherAddedFragments(@NonNull AppCompatActivity activity, @NonNull Fragment fragment) {
    FragmentManager fragmentManager = activity.getSupportFragmentManager();
    for (Fragment frag : fragmentManager.getFragments()) {
        if (frag != null && !frag.equals(fragment) && frag.isAdded()) {
            fragmentManager.beginTransaction().remove(frag).commit();
        }
    }
}

I am calling this in my onResume to be sure that it will be called also when I navigate back to the fragment.

Upvotes: 0

G&#246;rkem Bendin
G&#246;rkem Bendin

Reputation: 101

After about 1 week, I found the solution without adding background color or anything else. Just add this code and fix that bullshit. I hope it will help all of you.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    container.clearDisappearingChildren();
    return inflater.inflate(R.layout.fragment, container, false);
}

Upvotes: 10

Niels
Niels

Reputation: 9394

We went live with this version and havent received any complaints about this, so I will assume this was the correct answer:

in your onCreateView method add:

if (container != null) {
    container.removeAllViews();
}

Be sure to check if container is not null!

Thanks https://stackoverflow.com/users/2677588/lia-pronina!

Upvotes: 39

Miguelost
Miguelost

Reputation: 59

Add in the every layout

android:background="#FFFFFF"

The layouts background in default are transparen, so just put a background color and the new elements fragment, not display over old fragment

Upvotes: 2

Linh Nguyen
Linh Nguyen

Reputation: 1264

let's try with

fragmentManager.beginTransaction().executePendingTransactions();

after you call commit() method

Upvotes: 0

Related Questions