77

I have a 3 fragments in an activity when the a tablet is held in portrait. However I only have 2 of these fragments when in landscape. The problem I am having is when going from portrait to landscape the activity is creating the 3rd fragment. I receive and error as this fragment cannot be created.

I have worked out that this fragment is being created because it is in the back stack.

I have tried to remove the fragment in the onDestroy method by using

FragmentTransaction f = fragmentManager.beginTransaction();
f.remove(mf);
f.commit();

However the I get an error saying that I cannot use this function after the onSaveInstanceState

What would be the correct way of taking this fragment out of the back stack?

Update

I should probably add that the fragment I am having problems with is a mapFragment from this libary

https://github.com/petedoyle/android-support-v4-googlemaps

The way I use it is like so

mf = MapFragment.newInstance(1, true);

ft = fragmentManager.beginTransaction();
ft.replace(R.id.mapContainer, mf);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack("map");
ft.commit();
Ziem
  • 6,579
  • 8
  • 53
  • 86
jiduvah
  • 5,108
  • 6
  • 39
  • 55

5 Answers5

182

You add to the back state from the FragmentTransaction and remove from the backstack using FragmentManager pop methods:

FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove(myFrag);
trans.commit();
manager.popBackStack();
Elnur Abdurrakhimov
  • 44,533
  • 10
  • 148
  • 133
user123321
  • 12,593
  • 11
  • 52
  • 63
  • 68
    What happens if the fragment that you want to remove is not on top of the stack? – Kuno Sep 10 '13 at 07:51
  • 3
    yeah, i tired not working when fragment is not top of the stack.. Still trying to figure that! – AJit Oct 24 '13 at 20:38
  • Did you find a solution to that problem ? – An-droid May 12 '14 at 13:59
  • 3
    If you know beforehand that the fragment should not be part of the backstack, you might leave the "addToBackstrack(null)" out. – marktani Jan 05 '16 at 20:13
  • seems works http://i.imgur.com/nbHCM9P.png , but not clear fully why not ? I get a minium increment :( –  Mar 17 '16 at 14:59
  • 6
    i wonder why i had to call manager.popBackStack() after doing the remove. i would have though just the remove transaction would have gotten rid of it, thanks – j2emanue Jun 04 '18 at 17:56
  • I have 3 fragments. I want to remove only two fragments and replace another fragment in the same container. When I do fragmentManager.popBackStack(), previous(remaining one) fragment flashes for 1 second and then another fragment loaded. Is there any way to hide this transaction from the user? – Aanal Shah Dec 24 '18 at 05:55
23

I created a code to jump to the desired back stack index, it worked fine to my purpose.

ie. I have Fragment1, Fragment2 and Fragment3, I want to jump from Fragment3 to Fragment1

I created a method called onBackPressed in Fragment3 that jumps to Fragment1

Fragment3:

public void onBackPressed() {
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(fragmentManager.getBackStackEntryCount()-2).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}

In the activity, I need to know if my current fragment is the Fragment3, so I call the onBackPressed of my fragment instead calling super

FragmentActivity:

@Override
public void onBackPressed() {
    Fragment f = getSupportFragmentManager().findFragmentById(R.id.my_fragment_container);
    if (f instanceof Fragment3)
    {
        ((Fragment3)f).onBackPressed();
    } else {
        super.onBackPressed();
    }
}
SeniorJD
  • 6,946
  • 4
  • 36
  • 53
Klaus Skate
  • 247
  • 2
  • 2
  • 4
    But the code would turn messy in case of a large number of fragments, right? (I have 20 fragments) – Kathir Feb 06 '19 at 15:25
  • @Kathir `val backPressController = currentFragment as? BackPressController` `?: return handleBackPress()` `val shouldPerformBackPress = backPressController.onBackPressed()` `if (shouldPerformBackPress) handleBackPress()` – Tamim Attafi Jan 11 '22 at 17:38
2

you show fragment in a container (with id= fragmentcontainer) so you remove fragment with:

 Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragmentContainer);
            fragmentTransaction.remove(fragment);
            fragmentTransaction.addToBackStack(null);
            fragmentTransaction.commit();
AlimItTech
  • 172
  • 1
  • 9
0

In case you ended up here trying to figure out how to remove fragment(s) from backstack and you are using Android Jetpack Navigation component you could just use app:popUpTo and app:popUpToInclusive in action node of navigation graph xml to specify fragments that you want to pop out of back stack. https://developer.android.com/guide/navigation/navigation-navigate#pop Check this too https://stackoverflow.com/a/51974492/4594986

Ppp
  • 515
  • 5
  • 11
-13

What happens if the fragment that you want to remove is not on top of the stack?

Then you can use theses functions

popBackStack(int arg0, int arg1);

popBackStack(String arg0, int arg1);

Dornathal
  • 882
  • 9
  • 16
  • 24
    I think this is wrong, if you read the documentation "... all states `up to that state` will be popped" so it doesn't remove exactly that fragment, it will remove everything on top of it in the stack (and the fragment itself depending of flag). – User Jan 22 '14 at 23:07
  • 1
    I don't see why people are downvoting Dornathal's answer and upvoting @lxx 's comment! That's how stacks work [by definition](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))! – iSWORD Jun 03 '16 at 16:45
  • 2
    @iSWORD Because the question also implies how you can remove only one fragment which is not on top – teh.fonsi Feb 21 '17 at 12:46