navigation between 2 fragments - android

i have 2 fragments A and B in my application.
the mainactivity starts up with fragment A. on pressing a button in it i replace it with fragment B.
FragmentManager fm = getSupportFragmentManager();
B_Fragment pfrag = new B_Fragment();
pfrag.setArguments(args);
fm.beginTransaction().replace(R.id.frag_container, pfrag)
.addToBackStack("A_Fragment").commit();
Now in fragment B i press a button to replace it with fragment A using:
fm.popBackStack();
fm.beginTransaction().addToBackStack("B_fragment").commit();
Fragment A is successfully pushed and popped from the stack where as fragment B is not.
Every time B_fragment is been destroyed and a new one is created.
So can someone tell me what i am missing and how to push fragment B onto the stack and pop A out at the same time.

FragmentManager fm = getSupportFragmentManager();
B_Fragment pfrag = new B_Fragment();
pfrag.setArguments(args);
fm.beginTransaction().replace(R.id.frag_container, pfrag).commit();
On Fragment B, why don't just replace it with Fragment A
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.pnlLeft, details);
ft.commit();
popBackStack does not load the last fragment, it's commonly used to pop the entire stack :
fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
before loading another fragment
beginTransaction()
replace() Or add()
commit()
When you press the button in Fragment B, try the below code. This will re-load the entire fragment.
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
}

Related

Fragment overlap after back button pressed

I have three fragments (fragmentA, fragmentB, FragmentC). The code goes from fragmentA to fragmentB and then fragmentB to Fragemnt C.
When I press the back button I go from fragmentC to fragmentA.
After the back button is pressed fragmentA is displayed but you can also see fragmentC behind it.
fragmentA
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction;
ft.repalce(R.id.container, fragmentB)
.addToBackStack("Null")
.commit();
fragmentB
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction;
ft.repalce(R.id.container, fragmentC)
.commit();
fragmentC
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction;
ft.repalce(R.id.container, fragmentC)
.commit();
When the back button is pressed I want to go from fragmentC to fragmentA and not have fragment C displayed in the background
In addToBackStack use null as param , not "Null"
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction;
ft.repalce(R.id.container, fragmentB)
.addToBackStack(null)
.commit();
you can try this when replacing fragment
Fragment frag=null;
frag=new Navigation_Help();
if(frag!=null){
FragmentManager fragmentManager=getSupportFragmentManager();
FragmentTransaction ft=fragmentManager.beginTransaction();
ft.replace(R.id.sacreenarea,frag);
//for not to back previous fragment remove next nile
ft.addToBackStack(null);
ft.commit();
}
I tried using #ADM duplicate link, it would take me to the fragment A but if I loaded fragment B for a second time I would get double commit errors.
The solution that works for me is to restart the activity with the #Override onBackPressed(), this will reload the fragmentA by default.
Fragment B
FragmentManger fm = fragmentManager();
FragmentTransaction ft = fm.beginTransaction();
fm.replace(R.id.container, fragmentC, "fragmentC");
.commit();
fragmentC backbutton pressed
Activity
#Override
public void onBackPressed() {
if(getSupportFragmnetManager().findFragmnetByTag("fragmentC") !=null) {
Intent myIntent = new Intent(this, Activity.class);
startActivity(myIntent);
finish();
} else {
super.onBackPressed();
}
}
This solution will only work if you want to go back to the first fragment loaded by the Activity, so it may not be the best solution out there but it worked for me.

Add only one instance of fragment into backstack

I have implemented fragments in my application. Here my code for swiching fragment in fragment_container.
private void switchFragment(Fragment fragment, boolean isAddToBackStack, String tag)
{
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container, fragment, tag);
if (isAddToBackStack)
ft.addToBackStack(tag);
setCurrentTopFragment(Integer.parseInt(tag));
ft.commit();
}
I have 4 fragments A,B,C and D and for switching between this fragmnets I am using above method. I have A,C,B in my backstack. If again I switch to fragmnet A, my backstack is like A,C,B,A. What I actually want is If I swich to A again I want backstack sequence like this C,B,A. Means Remove old instance from backstack and add new to it.
First get the back-stacked Fragment by id which you need to remove:
Fragment fragment = getSupportFragmentManager().getFragment(new Bundle(), TAG_KEY)
or there are several methods getBackStackEntryCount(), getBackStackEntryAt. After getting the fragment which you need to remove. Remove it from the fragment back-stack.
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction trans = manager.beginTransaction();
trans.remove(fragment);
Then you can add a new fragment Done :)

How to replace more than one fragments with another one in the back stack?

I have the following fragments in the back stack A, B, C. Then I want to add fragment D, but in the back stack I want to put A and D instead of A, B, C, D.
The problem is when I try to remove B and C with transaction.remove(), the backStackEntryCount is still the old one, which makes empty screens while pressing back. Is there a way to handle this?
When I use popBackStack()it goes to fragment A then comes D, which makes weird animation effects.
EDIT:
The question is not duplicate as it was marked, because this question is more about to control the order of several fragments in the back stack.
When adding to the Backstack, you can include a name to pop the backstack to when you're in a specific state. Based on the documentation for FragmentManager#popBackStack(string, int);:
Pop the last fragment transition from the manager's fragment back stack. If there is nothing to pop, false is returned. This function is asynchronous -- it enqueues the request to pop, but the action will not be performed until the application returns to its event loop.
Parameters
name String: If non-null, this is the name of a previous back state to look for; if found, all states up to that state will be popped. The POP_BACK_STACK_INCLUSIVE flag can be used to control whether the named state itself is popped. If null, only the top state is popped.
flags int: Either 0 or POP_BACK_STACK_INCLUSIVE.
So in this case you:
Add fragment A to the container and to the root backstack. Give it a name so you can reference it when popping.
Fragment A:
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, FragmentA, "FragmentA")
.addToBackStack("first")
.commit();
Add Fragment B to the container (replace or add, doesn't matter). Add to the backstack with a "null" or another name if you prefer. It must be different than "first".
Fragment B:
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, FragmentB, "FragmentB")
.addToBackStack(null)
.commit();
Add or replace with Fragment C like you would with Fragment B.
Fragment C:
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, FragmentC, "FragmentC")
.addToBackStack(null)
.commit();
Add or replace with Fragment D like you would with Fragment B and C.
Fragment D:
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, FragmentD, "FragmentD")
.addToBackStack(null)
.commit();
Then, in onBackPressed() you first check if "FragmentD" is in the stack. If it is, then pop all the way back to the root (which in this case is "first"). If not, just handle the back pressed like you normally would.
#Override
public void onBackPressed() {
FragmentManager fm = getFragmentManager();
if (fm.findFragmentByTag("FragmentD") != null) {
fm.popBackStack("first", 0); // Pops everything up to "first"
} else {
super.onBackPressed(); // Pops backstack like normal or leaves App if at base.
}
}
What this should do is allow your users to go "back" when they press the back button in Fragments A, B, or C. Then when they're finally in Fragment D, it will pop all the way back to A.
Fragment A
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, FragmentA, "FragmentA");
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
Fragment B
fragmentTransaction.replace(R.id.fragment_container, FragmentB, "FragmentB");
Fragment C
fragmentTransaction.replace(R.id.fragment_container, FragmentC, "FragmentC");
Fragment D
fragmentTransaction.replace(R.id.fragment_container, FragmentD, "FragmentD");
Now your onBackPressed() in activity
#Override
public void onBackPressed() {
int lastStack = getSupportFragmentManager().getBackStackEntryCount();
try {
//If the last fragment was named/tagged "three"
if (getSupportFragmentManager().getFragments().get(lastStack).getTag().toString()=="FragmentD"){
getSupportFragmentManager().popBackStackImmediate();//skip c
getSupportFragmentManager().popBackStackImmediate();//skip B
Fragment fragment = getSupportFragmentManager().findFragmentByTag("FragmentA");
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.commit();
return;
}
} catch (Exception e) {
e.printStackTrace();
}
super.onBackPressed();
}
make fragment_container for each of the fragment and keep on replacing the newest fragment's fragment_container..
Dont forget:
addToBackStack(null);

How to reopen a fragment with saved instance from another fragment?

I have 1 activity with multiple fragments. These fragments call each other, for example fragment a calls fragment b:
Fragment a:
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_container, new FragmentB());
ft.commit();
Where OrderAddFragment is fragment b.
Now, let's say a user has filled in multiple inputs in fragment a and continues to fragment b but than he realises he made a mistake in fragment a and needs to go back to correct this mistake.
How could I reopen fragment a with the saved instance state instead of creating a new instance?
The back function in fragment b uses following code to reopen fragment a:
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_container, new FragmentA());
ft.commit();
FragmentTransaction.addToBackStack() might solve your problem.

How to delete a specific fragment from back stack in android

I have a problem about removing a specific fragment from back stack.My scenario is like this.Fragment-1 is replaced with Fragment-2 and then Fragment-2 is replaced with Fragment-3.
Calling order; Fragment-1-->Fragment-2-->Fragment-3.
When Fragment-3 is on the screen and then back button is clicked, i want to go
Fragment-1.That means i want to delete Fragment-2 from back stack.
How to do this ?
In the backstack you don't have Fragments, but FragmentTransactions. When you popBackStack() the transaction is applied again, but backward. This means that (assuming you addToBackStackTrace(null) every time) in your backstack you have
1->2
2->3
If you don't add the second transaction to the backstack the result is that your backstack is just
1->2
and so pressing the back button will cause the execution of 2->1, which leads to an error due to the fragment 2 not being there (you are on fragment 3).
The easiest solution is to pop the backstack before going from 2 to 3
//from fragment-2:
getFragmentManager().popBackStack();
getFragmentManager().beginTransaction()
.replace(R.id.container, fragment3)
.addToBackStack(null)
.commit();
What I'm doing here is these: from fragment 2 I go back to fragment 1 and then straight to fragment 3. This way the back button will bring me again from 3 to 1.
I had a very similar scenario to yours, my solution was just checking the amount of backStack transactions that I had.
If the transactions where more than 0 then I would simply pop it right away
so it would skip it when pressing back.
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStackImmediate();
}
...
fragmentTransaction.replace(R.id.main_fragment, newFrag, MAIN_FRAGMENT_TAG);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.commit();
This would successfully:
A -> B (back pressed) -> back to A
A -> B -> C (back pressed) -> back to A
The only downside that I see is that there is a quick flash where fragment A is displayed before going to fragment C.
If you are adding/launching all three fragments in the same activity, instead of the add(), use replace() (replace Fragment2 with Fragment3). The replace method removes the current fragment from backstack before adding the new one. If you are launching Fragment3 from a different activity, and thus you can't use replace(), remove Fragment2 from backstack before starting the new activity (which adds Fragment3):
// in Fragment2, before adding Fragment3:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.remove(this) // "this" refers to current instance of Fragment2
.commit();
fragmentManager.popBackStack();
// now go ahead and launch (add) fragment3
// if fragment3 is launched from a different activity,
// start that activity instead
fragmentManager.beginTransaction()
.add(R.id.a_container_view_in_activity, new Fragment3(),
Fargment3.FRAGMENT3_ID)
.commit();
Code for Fragment A -> Fragment B:
Add Fragment A in BackStack of Fragments
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout_container, new fragmentB());
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
Code for Fragment B -> Fragment C:
Do not Add Fragment B in BackStack of Fragments
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_layout_container, new fragmentC());
fragmentTransaction.commit();
It will works in this way: A -> B -> C and while returning C-> A as you excepted.
Hope it will help you.
for (int i = 0; i < mFragmentManager.getBackStackEntryCount(); i++) {
currentFragment = mFragmentManager.getFragments().get(i);
if (!(currentFragment instanceof ParticularFragment))
mFragmentManager.popBackStack();
else
break;
}

Categories

Resources