7

I have an Activity with three Fragments lets call them A, B and C. Fragment A is called in the Activity onCreate().

FragmentA fragA = new FragmentA();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.activity2_layout, fragA, "A");
transaction.commit();

And gets replaced with Fragment B or C when certain buttons are pressed, and the FragmentTransaction calls addToBackStack().

FragmentB fragB = new FragmentB(); //or C
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.activity2_layout, fragB, "B");  //or C
transaction.addToBackStack("B"); //or C
transaction.commit();

But lets say I call Fragment B three times in a row, how can I prevent it from stacking on to it self? And at the same time I want this to be possible: B called > C called > B called - BUT when i try to go back I want B to be opened only once ( C < B) instead of (B < C < B). So basically removing the first backStack with the new one.

Ivan Javorovic
  • 253
  • 1
  • 3
  • 8

2 Answers2

13

From How to resume Fragment from BackStack if exists, which maybe very similar to your query.

There is a way to pop the back stack based on either the transaction name or the id provided by commit (for eg. using the Fragment's class name as Thijs already mentioned):

String backStateName = fragment.getClass().getName();

Adding to backstack:

FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();

When popping:

getSupportFragmentManager().popBackStackImmediate (backStateName, 0); 

So before replacing fragment, we can check existance in backstack like:

boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);

if (!fragmentPopped){ //fragment not in back stack, create it.
    ...
    ...
    ft.addToBackStack(backStateName);
    ft.commit();
}

Please check the above question and the accepted answer for more explanation.

Community
  • 1
  • 1
Abu Ruqaiyah
  • 1,516
  • 1
  • 12
  • 20
1

I have solved one of your questions, namely how can I prevent it from stacking on to it self?, in one of my own projects a while ago. This was the exact code I used there:

public void setContent(@NonNull Fragment fragment, boolean addToBackStack) {
    Fragment current = getSupportFragmentManager().findFragmentById(R.id.main_content);
    if (current == null || !current.getClass().equals(fragment.getClass())) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        if (addToBackStack) {
            transaction.addToBackStack(null).add(R.id.main_content, fragment).commit();
        } else {
            transaction.replace(R.id.main_content, fragment).commit();
        }
    }
}

What this code does is checks of what class the currently showing Fragment is and compare that to the fragment you want to replace it with. If they are the same, it doesn't do anything. This code can be shaped to fit your needs like so

Fragment newFragment = new FragmentB(); //OR FragmentC
Fragment current = getSupportFragmentManager().findFragmentById(R.id.activity2_layout);
if (!current.getClass().equals(newFragment.getClass())) {

    //POP BACKSTACK HERE LIKE EXPLAINED BELOW

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    final String tag = newFragment.getClass().getSimpleName();
    transaction.addToBackStack(tag);
    transaction.add(R.id.activity2_layout, newFragment, tag);
    transaction.commit();
} else {
    //THROW AN ERROR OR SOMETHING, HANDLE IT BEING THE SAME
}

Making sure that only one fragment of a certain type is present at a time could probably be achieved by popping the backstack until before the first occurence of the same fragment. I have not written any code for this but it shouldn't be too difficult to implement that feature. If you can't figure it out yourself, let me know and I will try to write you an example :)

Thijs Koppen
  • 315
  • 1
  • 12
  • Thank you :) No a example wont be necessary :) The only thing i need to figure out now is how to remove backStacks which have already been made, if it's even possible since I can't find any documentation or examples on that. – Ivan Javorovic Nov 17 '15 at 14:28
  • 1
    I don't think that's possible at all. As far as I know, the `FragmentManager` has one and only one backstack. You can pop entries off and then add another to "replace" that amount of entries with the one new entry. As long as you do this before you `commit()`, you should be fine :) – Thijs Koppen Nov 17 '15 at 14:31
  • @IvanJavorovic by remove backStacks do you mean clearing the back stack? – Abu Ruqaiyah Dec 21 '16 at 11:20