FragmentTransaction: replace and addToBackStack not working together?

I am new to Android development and am now confused about strange behavior.

  • I have an empty FrameLayout as a fragment container.
  • If the user clicks the button for the first time, generates a new fragment and places it inside the container.
  • If the user clicks the button later and there will be an existing fragment inside the container, replace the existing one with a new one.
  • If the user clicks the back button, remove the fragment inside the container.

Here is my code

public void showFragment(View v) { FragmentA f = new FragmentA(); FragmentManager fm = getSupportFragmentManager(); String tag = f.getFragmentTag(); // instance method of a to get a tag FragmentTransaction ft = fm.beginTransaction(); ft.setCustomAnimations(R.anim.slide_in_top, 0, 0, R.anim.slide_out_top); ft.replace(R.id.container, f, tag); ft.addToBackStack(tag); ft.commit(); } @Override public void onBackPressed() { FragmentManager fm = getSupportFragmentManager(); if (fm.getBackStackEntryCount() > 0) { fm.popBackStack(); } else { super.onBackPressed(); } } 

When the user clicks the button for the first time, he behaves as I expected, adding a new fragment to the container. But the second time the user presses the button while the container still contains the fragment, instead of replacing it, it adds a new one on top of the existing one. So, 2 fragments inside the container, 2 back click to delete the entire fragment.

I found that if I delete the line

 ft.addToBackStack(); 

And recycle the onBackPress () method as shown below, it works again as I expected (1 fragment in the container at a time)

basically manually remove the snippet instead of the popFromBackStack method

 private FragmentA currentFragment = null; // to hold the reference to exising fragment, if any. @Override public void onBackPressed() { if (currentFragment != null) { FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); ft.setCustomAnimations(0, R.anim.slide_out_top); ft.remove(currentFragment); ft.commit(); currentFragment = null; } else { super.onBackPressed(); } } 

So my question is:

  • replace and addToBackStack not working together?
  • or did i do something wrong?

Appreciate all comments and suggestions.

+8
android android-fragments fragmenttransaction
source share
2 answers

addToBackstack takes a snapshot of the state of your snippets. This means that when you press the back button, you actually return to the last state in which addToBackstack was called.

In your case, you add a fragment. The back button will remove this added snippet. When you call replace and add backstack again, you now have two states in the backstack (1. when you added the first fragment, 2. if you did not have the added fragments). If you use the back button to delete the current fragment, do not use addToBackstack. Use addToBackstack only if you want to keep the state of fragments in the view.

+13
source share

For those who are still looking for a solution.

In the main class, the Activity (which places the fragments) simply overrides onBackPressed() .

 @Override public void onBackPressed() { if (getFragmentManager().getBackStackEntryCount() > 0 ){ getFragmentManager().popBackStack(); } else { super.onBackPressed(); } } 

There is no onBackPressed() method in the fragment, and this method is intended only for Activity . So, when we press the back key, the default behavior of Activity displayed, which is equal to

You will either go to the previous action (if any) or exit the application.

Now we need to override this method to tell Activity that when we press the back key, if there are any fragments on the stack, pull them out (and this will happen when addToBackStack() appears in the picture). Otherwise, follow the default behavior.

find more information here here

-2
source share

All Articles