Home » Android » Android Remove Fragment and View from BackStack

Android Remove Fragment and View from BackStack

Posted by: admin April 23, 2020 Leave a comment

Questions:

enter image description here

I realise this question has been asked before however the previous answers have gotten me so far. The scenario is as follows: we have a dashboard fragment (A), which leads a user to a login screen (B). On successful login they go to a listview (c). On backpress I would like to return to A, as the user will not need to see the login screen again. In addition on successful login we store the details in shared preferences and automate the login in B next time, which all works as planned.

I have the following FragmentHelper method:

public static void goToNextFragement(Fragment fragment, int container, boolean addToBackStack, Fragment ctx)
    {
        // Create new fragment and transaction
        FragmentTransaction transaction = ctx.getSupportFragmentManager().beginTransaction();
        transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
        // Replace whatever is in the fragment_container view with this fragment,
        // and add the transaction to the back stack
        transaction.replace(container, fragment);

        if(addToBackStack)
            transaction.addToBackStack(null);

        // Commit the transaction
        transaction.commit();
    }

In the transaction from B to C I set the Boolean addToBackStack as false so that the transaction.addToBackStack(null); is not called. This again works well but after is where my problem starts.

When the user presses back on C and returns to A I can still see the inflated view of C under the view of A.

Any help would be appreciated. I hope my diagram helps keep this simple.

How to&Answers:

Couple of ways to handle this:

  1. I had a similar flow in my app and the way I solved it was by replacing the login fragment with a AlertDialog that’s fired from the main activity.
    So in your case, fragment A shows up on screen and if the main activity thinks it needs to show the login dialog, it shows the AlertDialog. This worked for me.

  2. When fragment A is enabled, it can check if fragment C is around by asking the FragmentManager. If it exists then remove it.

Answer:

I solved this.. within a line…

getFragmentManager().popBackStack();

or

getSupportFragmentManager().popBackStack()

this works when you are adding fragments and maintaining backstack (not replacing).

Answer:

f1 -> f2

Fragment2 f2 = new Fragment2();
this.getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.main_content,f2).addToBackStack(null).commit();

nothing out of the ordinary here. Than in fragment f2 this code takes you to fragment f3.

f2 -> f3

Fragment3 f3 = new Fragment3();
getActivity().getSupportFragmentManager().popBackStack();
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.main_content, f3).addToBackStack(null).commit();

I’m not sure by reading docs if this should work, this poping transaction method is said to be asynchronous, and maybe a better way would be to call popBackStackImmediate(). But as far I can tell on my devices it’s working flawlessly.

The said alternative would be:

final FragmentActivity activity = getActivity();
activity.getSupportFragmentManager().popBackStackImmediate();
activity.getSupportFragmentManager().beginTransaction().replace(R.id.main_content, f3).addToBackStack(null).commit();

Here there will actually be brief going back to f1 beofre moving on to f3, so a slight glitch there.

This is actually all you have to do and this answer can also help you alot..

Answer:

Not telling the FM that you want the transition from B to C to be added to the backStack means that when you hit back, the FM has no record of adding C, so it doesn’t remove it.

Answer:

Step 1 : When you’re in Fragment A and want to open Fragment B

getFragmentManager().beginTransaction()
.replace(android.R.id.content, new FragmentB(), FragmentB.class.getName()
.addToBackStack(null)
.commit();

Step 2 : When you’re in Fragment B, and want to open Fragment C

getFragmentManager().beginTransaction()
.replace(android.R.id.content, new FragmentC(), FragmentC.class.getName()
.disallowAddToBackStack() // << this to make Fragment B, not included in the backstack
.commit();

Step 3 : When you’in in Fragment C, and pressing device back button or getFragmentManager().popBackStack(); you will be opening Fragment A.

PS : In Activity use this getSupportFragmentManager(). If you’re in Fragment use this getFragmentManager()

Answer:

Hi I just wanted to share elegant solution I found.

public static void performNoBackStackTransaction(FragmentManager fragmentManager, String tag, Fragment fragment) {
final int newBackStackLength = fragmentManager.getBackStackEntryCount() +1;

fragmentManager.beginTransaction()
    .replace(R.id.content, fragment, tag)
    .addToBackStack(tag)
    .commit();

fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
  @Override
  public void onBackStackChanged() {
    int nowCount = fragmentManager.getBackStackEntryCount();
    if (newBackStackLength != nowCount) {
      // we don't really care if going back or forward. we already performed the logic here.
      fragmentManager.removeOnBackStackChangedListener(this);

      if ( newBackStackLength > nowCount ) { // user pressed back
        fragmentManager.popBackStackImmediate();
      }
    }
  }
});
}

Source with explained logic.