I need to be able to go through fragments like this: A->B->C1
When I'm on C1 I need to replace it with C2, but when I press back I should be taken back to B instead of C1.
I'm able to do this like this:
String tag = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
manager.popBackStack();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.mainActivity_container, fragment, tag);
ft.addToBackStack(tag);
ft.commit();
The problem is that while I'm changing from C1 to C2, fragment B gets it's onCreateInnerView method called.
I need to be able to do something like this: A->B->C1->C2->C1->C2 and by pressing back in C2 I should go to B
How to execute replacement without recreating fragment B?
You can handle the onBackPressed() event and replace whatever is the current fragment to fragment B.
First thing You don't need to popupstack while moving to fragment. Because It will call your last stack's fragment onViewCreated method.
While moving to B -> C1 , B -> C2 and C1 -> C2 :
Need to add Back stack null
Remove popupbackstack
I hope it will works for you.
Try this might be help you,
Just replace two line ,
manager.popBackStack();//Remove this line
ft.replace(R.id.mainActivity_container, fragment);//Remove 3rd param in this line
ft.addToBackStack(tag);//Remove this line
EDITED
you can also try this
public void switchContent(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
for (int i = 0; i < fragmentManager.getBackStackEntryCount(); ++i) {
Fragment currentFragment = this.getSupportFragmentManager().findFragmentById(R.id.mainActivity_container);
if(currentFragment != B){
fragmentManager.popBackStack();
}
}
fragmentTransaction.replace(R.id.mainActivity_container, fragment).commit();
}
Since I don't know how many views I need so I have to create them dynamically. Based on my research that each fragment has to have a container, they can't share (Correct me if i'm wrong), so I need to create view container for each fragment dynamically, then I can have this:
for(int i = 0; i < size ; i ++) {
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.disallowAddToBackStack();
ft.add(new ABCFragment(), TAG).commit();
}
Does anyone know how i can get this working? I'm new to android still.
Thanks!!!!
Define it in xml, it will work as container:-
<RelativeLayout
android:visibility="gone"
android:id="#+id/R.id.container_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparents"/>
To get dynamic number of fragments, define different tag name for that:-
for (int i=0;i<size;i++){
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.container_fragment, new DetailFragment(), tag.get(i));
ft.commit();
}
You can give different tag names under tag.get(i)
Assume if fragment stack is like D->C->A->B-C->A->B->C->A->B->A , i need to get the position of fragment A which is added to back stack first that is position 2 in my case.
you can find out the potion of fragment by using below code .
FragmentManager frgmanager = getFragmentManager();
for (int i = 0; i < frgmanager .getBackStackEntryCount(); i++) {
if (frgmanager .getBackStackEntryAt(i).getName().equalsIgnoreCase(tagname)) {
return i;
}
}
but please insert it to backstack with tag name.
fragmentTransaction.replace(android.R.id.tabcontent, fragment, tagname);
fragmentTransaction.addToBackStack(tagname);
I have a ViewPager to implement swipe between "holder" Fragments. And inside them I need to add multiple Fragments to their respective containers.
The problem is, Im using FragmentTransaction.add(containerID, fragment);, but since there are multiple holder Fragments in the ViewPager, all the Fragments get added on the same holder Fragment, and not in the one that is calling to add them.
Anyone has an idea on a good practice to go around this problem?
Here is the code where I add the Fragments inside the holder fragment.
arrayFragments = new ArrayList<DiaAgendaFragment>();
DiaAgendaFragment objFragment;
FragmentManager fm = getFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
//this will be set accordingly later for each fragment
Time dataFragment = new Time();
dataFragment.setToNow();
//instantiate and set fragments
for (int i = 0; i < 5; i++) {
objFragment = DiaAgendaFragment.newInstance(5, dataFragment);
arrayFragments.add(objFragment);
//pega a View pelo nome e adiciona o fragment
transaction.add(getActivity().getResources().getIdentifier("agenda5d_activity_fragment"+i, "id", getActivity().getPackageName()), arrayFragments.get(i));
//codigo de teste
dataFragment.monthDay += 1;
}
transaction.commit();
You have to use the child FragmentManager if you want to add Fragments to another Fragment. Using the normal FragmentManager will not work as you found out yourself.
In your Fragment:
FragmentManager manager = getChildFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
...
transaction.commit();
I ported my Android app to honeycomb and I did a big refactor in order to use fragments. In my previous version, when I pressed the Home button I used to do a ACTIVITY_CLEAR_TOP in order to reset the back stack.
Now my app is just a single Activity with multiple fragments, so when I press the Home button I just replace one of the fragments inside it. How can I clear my back stack without having to use startActivity with the ACTIVITY_CLEAR_TOP flag?
I posted something similar here
From Joachim's answer, from Dianne Hackborn:
http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42
I ended up just using:
FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
fm.popBackStack();
}
But could equally have used something like:
((AppCompatActivity)getContext()).getSupportFragmentManager().popBackStack(String name, FragmentManager.POP_BACK_STACK_INCLUSIVE)
Which will pop all states up to the named one. You can then just replace the fragment with what you want
To make an answer for #Warpzit's comment and make it easier for others to find.
Use:
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
With all due respect to all involved parties; I'm very surprised to see how many of you could clear the entire fragment back stack with a simple
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
According to Android documentation (regarding the name argument - the "null" in the claimed working proposals).
If null, only the top state is popped
Now, I do realize that I'm lacking knowledge of your particular implementations (like how many entries you have in the back stack at the given point in time), but I would bet all my money on the accepted answer when expecting a well defined behaviour over a wider range of devices and vendors:
(for reference, something along with this)
FragmentManager fm = getFragmentManager(); // or 'getSupportFragmentManager();'
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
fm.popBackStack();
}
Clear backstack without loops
String name = getSupportFragmentManager().getBackStackEntryAt(0).getName();
getSupportFragmentManager().popBackStack(name, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Where name is the addToBackStack() parameter
getSupportFragmentManager().beginTransaction().
.replace(R.id.container, fragments.get(titleCode))
.addToBackStack(name)
Works for me and easy way without using loop:
FragmentManager fragmentManager = getSupportFragmentManager();
//this will clear the back stack and displays no animation on the screen
fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Accepted answer was not enough for me. I had to use :
FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
fm.popBackStackImmediate();
}
Hi~I found a solution which is much better,from: https://gist.github.com/ikew0ng/8297033
/**
* Remove all entries from the backStack of this fragmentManager.
*
* #param fragmentManager the fragmentManager to clear.
*/
private void clearBackStack(FragmentManager fragmentManager) {
if (fragmentManager.getBackStackEntryCount() > 0) {
FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(0);
fragmentManager.popBackStack(entry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
I just wanted to add :--
Popping out from backstack using following
fragmentManager.popBackStack()
is just about removing the fragments from the transaction, no way it is going to remove the fragment from the screen.
So ideally, it may not be visible to you but there may be two or three fragments stacked over each other, and on back key press the UI may look cluttered,stacked.
Just taking a simple example:-
Suppose you have a fragmentA which loads Fragmnet B using fragmentmanager.replace() and then we do addToBackStack, to save this transaction.
So the flow is :--
STEP 1 -> FragmentA->FragmentB (we moved to FragmentB, but Fragment A is in background, not visible).
Now You do some work in fragmentB and press the Save button—which after saving should go back to fragmentA.
STEP 2-> On save of FragmentB, we go back to FragmentA.
STEP 3 ->So common mistake would be... in Fragment B,we will do fragment Manager.replace() fragmentB with fragmentA.
But what actually is happenening, we are loading Fragment A again, replacing FragmentB . So now there are two FragmentA (one from STEP-1, and one from this STEP-3).
Two instances of FragmentsA are stacked over each other, which may not be visible , but it is there.
So even if we do clear the backstack by above methods, the transaction is cleared but not the actual fragments.
So ideally in such a particular case, on press of save button you simply need to go back to fragmentA by simply doing fm.popBackStack() or fm.popBackImmediate().
So correct Step3-> fm.popBackStack() go back to fragmentA, which is already in memory.
For the kotlin people around here:
repeat(supportFragmentManager.backStackEntryCount) {
supportFragmentManager.popBackStack()
}
Reading the documentation and studying what the fragment id is, it appears to simply be the stack index, so this works:
fragmentManager.popBackStackImmediate(0, FragmentManager.POP_BACK_STACK_INCLUSIVE);
Zero (0) is the the bottom of the stack, so popping up to it inclusive clears the stack.
CAVEAT: Although the above works in my program, I hesitate a bit because the FragmentManager documentation never actually states that the id is the stack index. It makes sense that it would be, and all my debug logs bare out that it is, but perhaps in some special circumstance it would not? Can any one confirm this one way or the other? If it is, then the above is the best solution. If not, this is the alternative:
while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }
Just use this method and pass Context & Fragment tag upto which we need to remove the backstake fragments.
Usage
clearFragmentByTag(context, FragmentName.class.getName());
public static void clearFragmentByTag(Context context, String tag) {
try {
FragmentManager fm = ((AppCompatActivity) context).getSupportFragmentManager();
for (int i = fm.getBackStackEntryCount() - 1; i >= 0; i--) {
String backEntry = fm.getBackStackEntryAt(i).getName();
if (backEntry.equals(tag)) {
break;
} else {
fm.popBackStack();
}
}
} catch (Exception e) {
System.out.print("!====Popbackstack error : " + e);
e.printStackTrace();
}
}
It is working for me,try this one:
public void clearFragmentBackStack() {
FragmentManager fm = getSupportFragmentManager();
for (int i = 0; i < fm.getBackStackEntryCount() - 1; i++) {
fm.popBackStack();
}
}
I got this working this way:
public void showHome() {
getHandler().post(new Runnable() {
#Override
public void run() {
final FragmentManager fm = getSupportFragmentManager();
while (fm.getBackStackEntryCount() > 0) {
fm.popBackStackImmediate();
}
}
});
}
private void clearBackStack(){
SupportFragmentManaer fm = getSupportFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
Call to this method would be very neat.
No Loop required.
If you are using animation in fragments, it will not show too many animations. But using loop will.
private boolean removeFragFromBackStack() {
try {
FragmentManager manager = getSupportFragmentManager();
List<Fragment> fragsList = manager.getFragments();
if (fragsList.size() == 0) {
return true;
}
manager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}