Search code examples
androidandroid-fragmentsandroid-framelayoutfragmenttransaction

FragmentTransaction replace method doesn't work properly


I have a bug with replacing fragments inside FrameLayout container. When app is started first time everything is Ok but when I hide app and then resume it fragments start overlap each other when FragmentTransaction.replace method is called

I've seen almost all stackoverflow questions about such issues but I can't resolve this issue

Code:

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

Add initial fragment:

getSupportFragmentManager().beginTransaction()
                    .add(R.id.frame, RequestFragment.newInstance(), REQUEST_FRAGMENT_TAG)
                    .commit();

Replace:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
switch (menuItem.getItemId()) {
    case R.id.request:
        ft.replace(R.id.frame, RequestFragment.newInstance(), REQUEST_FRAGMENT_TAG);
        ft.commit();
        return true;
    case R.id.finished:
        ft.replace(R.id.frame, FinishedFragment.newInstance(), FINISHED_FRAGMENT_TAG);
        ft.commit();
        return true;
    case R.id.questions:
        ft.replace(R.id.frame, QuestionsFragment.newInstance(), QUESTIONS_FRAGMENT_TAG);
        ft.commit();
        return true;
    default:
        return true;
}

Solution

  • Difficult to say as your code provides no context as to when it is run but I suspect the issue is when you are adding your initial fragment.

    You are calling add instead of replace which will just add the new fragment on top of any existing ones. It is perfectly fine to use replace even if the container does not yet contain anything.

    Fragments survive in the FragmentManager and are automatically re-attached to their container when the Activity restarts. The correct procedure is to check for an existing Fragment before adding a new one.

    Add initial fragment

    Fragment f=getSupportFragmentManager().findFragmentById(R.id.frame);
    
    if (f==null) {
        getSupportFragmentManager().beginTransaction()
         .replace(R.id.frame, RequestFragment.newInstance(), REQUEST_FRAGMENT_TAG).commit();
    
    }
    

    Also, it is helpful to make use of logging getSupportFragmentManager().getFragments().size(); whilst you are debugging. It lets you know how many fragments are currently in the FragmentManager and can highlight potential issues in your code. For example, if your count goes up every time you rotate the device, you are adding fragments and not checking for existing ones.