I have 4 Fragments A B C D.
how to use back stack and how to set fragments?
I want to add just Fragment A to stack and when I press back button from B C or D, I want to to set fragment A.
I dont want B C and D in back stack
Normally in your FragmentTransaction you should call addToBackstack(null) to add it into backstack.
The backstack is actually a stack where you pop a Fragment when user presses back.
So if A puts B, B puts C and C puts D; you cannot go from D to A directly.
You can override onBackPressed() and control the behavior yourself without using the Fragment's builtin back stack support.
You can popbackstack to clear any fragments in history and ad to backstack fragment A like so :
//create an instance of the fragment you want o be avilable on back press
FragmentA fragmentA = new FragmentA();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
//Create instance of the fragment that is going to be loaded
FragmentD fragmentD = new FragmentD();
//Replace the current fragment with Fragment D
fragmentTransaction.replace(R.id.frame_container, fragmentD);
//Clear frgament history and include the fragment wanted on back press
fragmentManager.popBackStack();
fragmentTransaction.addToBackStack(fragmentA.getclass().getName());
fragmentTransaction.commit();
Related
MainFragment launches FragA that launches FragB that lunches FragC.
Back button press on FragB should go to FragA and back press on FragC should also go to FragA.
FragB is the only one where isToAddToBackStack is false.
childFragmentManager.commit {
replace(containerViewId, fragment, fragment::class.java.name)
if (isToAddToBackStack) {
addToBackStack(backStateName)
}
}
Whenever the back button is pressed on FragC, FragB is shown:
if (childFragmentManager.backStackEntryCount > 1) {
childFragmentManager.popBackStack()
return
}
What's the better way to achieve the navigation that I'm expecting?
Fragment transactions can involve two different types of tags. The one that most Android developers are familiar with is the Fragment tag, which you can use to find a specific Fragment in your FragmentManager later via findFragmentByTag(). This is useful for finding a Fragment when your application is in a particular state, but keep in mind that the Fragment needs to be added to your FragmentManager. If you have removed() or replaced() a Fragment and haven’t added it to the back stack, you won’t be able to find it.
The other type of tag is the BackStackRecord’s name passed into addToBackStack(). This name identifies a particular back stack record, which is a record of what occurred in a particular transaction. popBackStackImmediate() and its counterparts have variants that accept a back stack record name to pop the back stack to a particular state.
//fm is FragmentManager
// Fragment a is on the screen
Fragment a = new A_Fragment()
fm.beginTransaction()
.remove(null /*no fragments in R.id.content*/)
.add(R.id.content, aFragment, "fragment-a")
.commit();
// user wants to go from A to B
Fragment bFragment = new B_Fragment();
fm.beginTransaction()
.remove(fm.findFragmentById(R.id.content))
.add(R.id.content, bFragment, "fragment-b")
.addToBackStack("a")
.commit();
// user wants to go from B to C
fm.beginTransaction()
.remove(fm.findFragmentById(R.id.content))
.add(R.id.content, new C_Fragment(), "fragment-c")
.commit();
My App has only one activity and lots of fragments.
In my activty's XML, I just have a FrameLayout on which I replace/add/hide/show various fragments.
Imagine Fragment A is the first fragment the user sees when they open the app.
Click something in Fragment A to launch Fragment B and click something in Fragment B to launch Fragment C.
So the navigation is can be illustrated as follows :
Fragment A --> Fragment B --> Fragment C
I want to launch the app and show Fragment C directly from notification.
However, how can I provide back navigation from Fragment C, as such clicking back would go to Fragment B and clicking back again go to Fragment A ?
i.e How can I inject the following stack structure ?
Fragment A <-- Fragment B <-- Fragment C
Yes, you can do this. Since support library v26 you can build the stack with fragments without significant cost.
In your activity make the following:
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new FragmentA())
.addToBackStack("fragmentA")
.setReorderingAllowed(true)
.commit();
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new FragmentB())
.addToBackStack("fragmentB")
.setReorderingAllowed(true)
.commit();
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, new FragmentC())
.addToBackStack("fragmentC")
.setReorderingAllowed(true)
.commit();
Keep in mind that FragmentA and FragmentB will behave in a bit different way after pressing back on FragmentC due to setReorderingAllowed. onCreateView won't be called for FragmentA and FragmentB after they were added to stack, only in FragmentC onCreateView will be called. For FragmentA and FragmentB only onCreate will be called.
What you can do is -
Use a notification intent in which you pass a string. In your main activity if you receive that string make a fragment stack of A, B and C.
Else if you don't get the intent just continue your flow as it is.
I have got a problem regarding android fragments. I have 3 fragments say A, B and C. From A I move to B and I have an if statement that checks a value from shared preferences if value exists it move to C. If i press back button on Fragment C, it navigates to Fragment A but fragment C is also visible in background. Don`t know how to fix it. I have tried almost every solution from SO questions.
Here is my code
In fragment A on button click
Fragment fragment = new MyAccount();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).addToBackStack(null)
.commit();
In fragment B
if(RegDetails.contains("MSISDN")&&RegDetails.contains("PIN")){
Fragment fragment = new ReferFriend();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment)
.commit();
}
From B it move to c and works fine. But when I click back button on C fragment A is visible but fragment C is also visible in background.
I see two options:
Add a solid background (color) to your A-fragment's root view
Use .show() and .hide()
I have a form divided in few fragments. I call every fragment with:
final FragmentManager fm = getSupportFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
if(fragment.equals(this.formOne) || fragment.equals(this.formTwo)) {
ft.setCustomAnimations(android.R.anim.slide_in_left,android.R.anim.slide_out_right);
}
ft.replace(R.id.fragForm, fragment);
ft.addToBackStack(null);
ft.commit();
When I click on the back button it skips the previous Fragment and goes back to the Activity but with a blank screen.
For example, I have 3 fragments : A - B - C
If I go to C and want to go back to the previous Activity, I click on the back button so I'm on B, I click again and I'm on A, and when I click again, I have a blank screen, I need to click another time to come back to the previous activity.
I don't understand why have I this blank screen on my Activity.
I don't understand this in the developer documentation:
Note: You should not add transactions to the back stack when the
transaction is for horizontal navigation (such as when switching tabs)
or when modifying the content appearance (such as when adjusting
filters). For more information, about when Back navigation is
appropriate, see the Navigation design guide.
If we can't use that, what is the solution?
Don't add it to the backstack when you add fragment A.
ft.add(R.id.fragForm, fragmentA);
ft.commit();
ft.replace(R.id.fragForm, fragmentB);
ft.addToBackStack(null);
ft.commit();
ft.replace(R.id.fragForm, fragmentC);
ft.addToBackStack(null);
ft.commit();
If you don't have to Navigate to previous fragment don't add it to the backstack
Remove this
ft.addToBackStack(null);
Activity 1 is visible. Press a button, and Activity 2 opens.
Activity 2 adds fragment A to itself (and back stack) and it displays fine
Pressing a button within the fragment transitions to another fragment, B
Press Back. Nothing happens. Huh? The Back press is seemingly absorbed and not acted upon, the display remains the same.
Press Back a second time, it reverts to the Activity 1, as expected.
Why is my fragment not being shown in step 4? I've added the fragment to the back stack, so why (when the Back button seems aware of its existence) does it not show the fragment?
Here's the code I'm using in Activity 2 to open Fragment A.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_profile_edit);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
transaction.addToBackStack(null);
transaction.add(android.R.id.content, new MyFragment());
transaction.commit();
}
And here's the code to open Fragment B
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
transaction.add(android.R.id.content, new MyOtherFragment());
transaction.commit();
Have you tried transaction.replace(...) instead of transaction.add(...)? That should work. I'm guessing because if you're just adding a fragment over another, it doesn't see transaction as wanting to go back fro Fragment A.
EDIT
The actual answer for the question is below in the comments: addToBackStack() should be used on the fragment which is replacing, not the one being replaced.