50

Activity layout picture

Assume I have an Activity which contains two FrameLayouts (let's call them FrameA and FrameB) which in turn each contain a Fragment (let's call them FragmentA1 and FragmentB1 respectively). Now, I commit a series of individual fragment transactions using code similar to the following...

getFragmentManager()
 .beginTransaction()
 .replace(frameId, fragment)
 .addToBackStack(null)
 .commit();

... such that I replace FragmentA1 in FrameA with FragmentA2, then I replace FragmentB1 in FrameB with FragmentB2, then I replace FragmentA2 in FrameA with FragmentA3, then I replace FragmentB2 in Frame2 with FragmentB3, and the final state looks like the picture above (where only FragmentA3 and FragmentB3 are visible).

If I understood correctly how the back stack works, pressing 'back' will interleave popping of the Fragments between FrameA and FrameB (reflecting how I added them).

Does anyone know if it is possible to pop the last transaction on FrameA or FrameB selectively? (i.e. if I pressed 'Pop FrameA' then FrameA would be transitioned back from FragmentA3 to FragmentA2 and, instead, if I pressed 'Pop FrameB' then FrameB would be transitioned back from FragmentB3 to FragmentB2)

Supplement: I know I can get the Fragment last added to a given FrameLayout using the FragmentManager.findFragmentById(int framelayoutId) method, but calling FragmentTransaction.remove(fragment).commit() only removes the Fragment from the View and does not transition the View back to the Fragment it previously displayed.

Adil Hussain
  • 30,049
  • 21
  • 112
  • 147
  • 1
    If FragmentTransaction.remove "only removes the Fragment from the View and does not transition the View", then what is showing in the view? But I can see why this could cause confusion if the Mgr keeps a single stack of fragments but is unaware of which ones are simultaneously visible, i.e., how would it know that A2 is "underneath" A3 when B2 might be in between them on the stack? – gordonwd Jan 07 '12 at 22:31
  • If a View (FrameLayout in my case) has had multiple Fragments added to it using the `FragmentTransaction.add(int, Fragment)` method, then calling `FragmentTransaction.remove(Fragment).commit()` I believe will leave the FrameLayout showing the Fragment last added to it. However, adding Fragments to the View using the `FragmentTransaction.replace(int, Fragment)` method (as I am doing, assuming this is better for memory?!) will leave the FrameLayout child-less (i.e. showing as an empty View)... – Adil Hussain Jan 08 '12 at 08:23
  • To add to my previous comment: I can see that there some useful methods like `FragmentManager.getBackStackEntryAt(int index)`, `FragmentManager.popBackStack(String name, int flags)`, `popBackStack(int id, int flags)`, `FragmentTransaction.addToBackStack(String name)` and `FragmentTransaction.replace(int containerViewId, Fragment fragment, String tag)`, just not sure how to pool them together to achieve what I require... – Adil Hussain Jan 08 '12 at 08:30
  • That's exactly my problem and I am still searching for answers... – TheOnlyAnil Sep 05 '15 at 11:53

2 Answers2

26

Basically, no, there is only one back stack for an activity.

You will just need to implement your own separate back stacks.

As of Android 4.0 (and the associated support library) there are APIs that should make this relatively easy -- FragmentTransaction.detach(Fragment) lets you put a fragment into the same state it is when in the back stack, and FragmentManager.saveFragmentInstanceState(Fragment) lets you go further and completely throw away the Fragment object. Not coincidentally, these are used to implement ViewPager's FragmentPagerAdapter and FragmentStatePagerAdapter, respectively, so you could look at the code for these as an example of how to use them.

hackbod
  • 90,665
  • 16
  • 140
  • 154
  • Thanks for the response Hackbod. I had to make progress with what I knew so implemented a solution where I'm hiding Fragment A1 before _adding_ (rather than _replacing_) Fragment A2 on top of it, and then _showing_ Fragment A1 again when Fragment A2 is removed. It's working for me but will definitely go with implementing my own back stacks as you described in future projects or if any undesired behaviours surface in the present one :-\ Thanks again. – Adil Hussain Jan 17 '12 at 11:40
15
FragmentManager.popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)

Here is the simplest answer, and the explanation is very clear: Well there are a few ways to go about this depending on the intended behavior, but this link should give you all the best solutions and not surprisingly is from Dianne Hackborn...

Hai-Yang Li
  • 376
  • 2
  • 4
  • How does this answer the question? The question is about selectively popping interleaved *parts* of the back stack, not popping everything off the back stack back to a certain point (which is what `popBackStack()` does). – LarsH Nov 13 '19 at 14:59
  • Also, the link here points to a question, not an answer. The question there has several different answers, rather than a single clear one. Maybe you're referring to the accepted answer by Joachim? (https://stackoverflow.com/a/5984892/423105) – LarsH Nov 13 '19 at 15:03
  • 1
    @LarsH Your suggestion is more precise, so I corrected the link to the right answer, thank you. – Hai-Yang Li Jun 12 '20 at 18:03