Remove fragments that are not put on backstack - android

My simple layout only has a fragment placeholder:
<FrameLayout
android:id="#+id/fragment_placeholder"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
I firstly add a 1st fragment to this placeholder:
fragmentTransaction.add(R.id.fragment_placeholder, firstFragment, "first"); //I did not put to backstack
I have a 2nd fragment, which replace the above fragment and put it to back stack:
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMgr.beginTransaction();
//initialize an fragment instance
Fragment secondFragment = initSecondFragment();
//replace with the fragment
fragTrans.replace(R.id.fragment_placeholder, secondFragment, "second");
//Add fragment transaction to back stack
fragTrans.addToBackStack(null);
//commit the transaction
fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragTrans.commit();
Later I have some fragments replace the previous fragment, but NOT put on backstack.
It seems for those fragment which have not been put on backstack will always showing on screen, the back button press will have not effect to them.
So, How to find those fragments which are not on backstack in my app, and how to remove them from screen?

How to find those fragments which are not on backstack in my app
Call findFragmentById() or findFragmentByTag() on your FragmentManager.
how to remove them from screen?
Use remove() with a FragmentTransaction.

Related

android fragments - if i add two fragments on top of each other what is callback when top one is removed?

when i have two fragments that are stacked on top of each other in a framelayout using "add" transaction how can i know what the call back is when one is removed.
so imagine i have a framelayout like this:
<FrameLayout
android:id="#+id/fl_cart_address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="4dp"/>
and then i add two fragments like this:
mFragment = new ExampleOneFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fl_cart_address, mFragment).commit();
mFragment = new ExampleTwoFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fl_cart_address, mFragment).commit();
now if i hit the back button then fragmentTwo is gone. but what call back can i get in FragmentOne so i know that its actually gone ? Basically i just need a callback when the top fragment gets popped off the backstack. I tried onResume but its not working.
use FragmentManager.OnBackStackChangedListener
Register a callback to using FragmentManager.addOnBackStackChangedListener(FragmentManager.OnBackStackChangedListener listener)
it will send you a callback when the Backstack is changing.

Why does not `replace` replace a fragment?

I have the following code that adds fragments to the same container R.id.container. First I add one fragment, then after user interacts with it, I add another one with the same code
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
My question when I cell getSupportFragmentManager().getFragments() I can see two fragments. Why doesn't replace actually replace but add?
It keeps the two fragments because
addToBackStack(null);
means the user is able to revert back to the previous state.
If you add fragment1 (using replace), then fragment2, only fragment2 is shown, but if the user press back, the FragmentManager needs to show fragment1, so it keeps a reference to both fragment.

Fragment with MapView is never removed from FragmentManager

I have a Fragment with MapView in it. I add Fragment to container with following code:
Fragment fragment = new MyLocationFragment()
String tag= fragment.getClass().getName();
FragmentTransaction transaction = fm.beginTransaction();
transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left,
R.anim.slide_in_left, R.anim.slide_out_right);
transaction.replace(R.id.container, fragment, tag);
transaction.addToBackStack(null);
transaction.commit();
Now when user presses back, this Fragment is supposed to be removed from FragmentManager. But if execute this code :
Fragment fragment = getSupportFragmentManager().findFragmentByTag(MyLocationFragment.class.getName());
It never returns null, even if I replace other fragments in same container. What can I do to remove Fragment from FragmentManager? Am I doing something wrong here ?
When an activity is destroyed, its FragmentManagersaves out its list of fragments. When the activity is recreated, the new FragmentManager retrieves the list and recreates the listed fragments to make everything as it was before.
[Refer to book "Android Programming The Big Nerd Ranch Guide" P150]
So your should remove fragment from fragmentmanager.
Refer to this Q&A Remove old Fragment from fragment manager
Your question maybe duplicate with thisHow to get a Fragment to remove itself, i.e. its equivalent of finish()?

FragmentTransaction add() behavior

Working with fragments I've always used replace() for my transactions, but I wish I didn't have to save instance states anymore to restore a fragment's view and prevent reloading when coming back to that fragment. So, I've decided to work with add(). The thing is when I add another fragment, the previous fragment view remains in the background and that's fine (that's the behavior I expected), but the problem is I can actually interact with the views in the background. Example:
Fragment A has a Button
Fragment B has a TextView
When I add Fragment A and later add Fragment B, I'm able to click on Fragment A's Button, even staying on Fragment B's view.
I'm using:
FragmentTransaction fragmentTransaction =
getSupportFragmentManager().beginTransaction().
add(getRootViewContainer(),fragment,fragment.getClass().getSimpleName());
if (shouldGoBack)
fragmentTransaction.addToBackStack(fragment.getClass().getSimpleName());
where getRootViewContainer() returns the id of the FrameLayout I'm using as my activity main container.
Now, is it really the default behavior of add()?
If so, is there a proper way to avoid this or one just has to use replace()?
What you can do here is just hide previous fragment at the time of transaction of current fragment.
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
Fragment newFragment= new MyFragment ();
ft.hide(CurrentFragment.this);
ft.show(newFragment);
ft.commit();
It worked for me just try it.
FragmentTransaction.hide(fragmentBehind); //works for me!
example :
//I have it globally available
FragmentTransaction trans = MainActivity.getManager().beginTransaction();
//not globally
FragmentTransaction trans = getFragmentManager().beginTransaction();
MapFragment newFragment = new newFragment();
trans.add(R.id.fragmentContainer, newFragment, tag);
trans.hide(this);
trans.addToBackStack(tag);
trans.commit();
Yes, this is a default behaviour of add().
If you really don't want to user replace(), you can try to disable views which are inside "old" fragment.

Manually adding Fragment to BackStack

I'm currently using a ViewGroup (SwipeyTab implementation) to switch between Fragments. However, some Fragment "pages" get replaced by other Fragments on the same Tab, so I initially tried:
FragmentTransaction ft = fragment.getFragmentManager().beginTransaction();
ft.remove(currentFragment);
ft.add(newFragment,"");
ft.commit();
That code would remove the current fragment but not add newFragment (from Logcat, it would get instantiated but not appear).
I ended up adding it in the FragmentPagerAdapter.getItem(int position) call based on current state (based on this: Replace Fragment inside a ViewPager). However, I'd like to be able to add each newly replaced fragment to be part of the back stack.
I tried adding to backstack before removing the fragment:
currentFragment.getFragmentManager().beginTransaction().addToBackStack(null).commit();
FragmentTransaction ft = fragment.getFragmentManager().beginTransaction();
ft.remove(currentFragment);
ft.commit();
and that didn't work - it added the last fragment to the backstack, so when I pressed back, it would just reload the current fragment.
Is there anyway I can add a fragment to the backstack that has been replaced in the "non traditional" way?

Categories

Resources