How to back on Fragments without FragmentTransaction? - android

I have 4 fragment in my android app :
let's say A B C D where they 4 are fragments called in 1 activity. When I go from A to B and from be to C I want the back button to bring me to B and to A if I press again. But instead the back button forwards me to the previous activity.
I've read that the back button need to explicitely be handled as for fragments and I saw that code :
FragmentTransaction tx = fragmentManager.beginTransation();
tx.replace( R.id.fragment, new MyFragment() ).addToBackStack( "tag" ).commit();
fragment.getView().setFocusableInTouchMode(true);
fragment.getView().setOnKeyListener( new OnKeyListener()
{
#Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
return true;
}
return false;
}
} );
The problem is that I'm not using any FragmentTransaction. Here is how I call my Fragments :
private void displayView(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new HomeFragment();
break;
/*case 1:
fragment = new ContactsFragment();
break;*/
case 2:
fragment = new ContactsFragment();
break;
case 3:
fragment = new SitesFragment();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
}
How can I use that back stacking with my code please ?
Thank you for your help in advance !

By calling .beginTransaction(), you are actually using a FragmentTransaction. The type itself is just not explicitly mentioned in your example. You can simply call addToBackStack() on the transaction to add the transaction to the fragment manager's back stack:
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).addToBackStack(null).commit();
Edit:
As Larry pointed out, adding to the fragment manager's back stack will automatically handle going back if your structure is as simple as A>B>C>D. If, for any reason, you need to manually handle the behavior of popping the backstack, you can use these instructions below:
In your activity, override onBackPressed() and call getFragmentManager().popBackStack(); Note: that you will need to know which fragment you are currently displaying so that you can safely call popBackStack on B, C, and D but if you are on A, you will want to (most likely) exit the activity. (Alternatively, you could only pop the back stack if there are items in it. For that, check if (getFragmentManager().getBackStackEntryCount() > 0)
Here's how your full fragment transaction code should look:
// the tag here is if you need to know which fragment is loaded, later
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment, tag).addToBackStack(null).commit();
Then, the back handler:
#Override
public void onBackPressed()
{
if (someCriteriaToDetermineIfBackStackShouldBePopped)
{
getFragmentManager().popBackStack();
return;
}
// this fragment is A (or something else) - let the parent handle the back press
// which will finish the activity
super.onBackPressed();
}
If you need help detecting which fragment is currently loaded, this should get you started: get currently displayed fragment

You need to use the FragmentTransaction to add/replace the new fragment, add it to the back stack, then commit. You do not need to handle the BACK button yourself unless you wish to override the default behavior. Adding it to the back stack in the FragmentTrasnaction before you commit will automatically pick up the desired BACK button support.

Related

Fragment and BackStack not working properly

My MainActivity contains a Navigation Drawer with two fragments. The first fragment is loaded automatically when the app starts. I want the app to switch from fragment two to fragment one when the back button is pressed or if the first fragment is added then exit the app. I am adding the fragmentTransaction of the first fragment to a stack and then calling popBackStack in my onBackPressed method. However the behaviour is pretty weird.
When I'm on the first fragment the application should exit (ie, execute super.onBackPressed) however when on the first fragment and pressing back the first fragment is removed from the fragmentholder leading to a blank screen and then on pressing the second time the app closes.
When I'm on the second fragment nothing happens when the back button is pressed the first time and on pressing the back button a second time the app closes. Here's the relevant code from the MainActivity.java
#Override
public void onBackPressed() {
if (musicService.isPng()) moveTaskToBack(true);
if (getFragmentManager().getBackStackEntryCount() > 0)
getFragmentManager().popBackStack("returnFragment", 0);
else super.onBackPressed();
}
private void loadSelection(int i) {
navList.setItemChecked(i, true);
switch (i) {
case 0:
FirstFragment firstFragment = new FirstFragment();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmentholder, firstFragment)
.addToBackStack("returnFragment")
.commit();
break;
case 1:
SecondFragment secondFragment = new SecondFragment();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragmentholder, secondFragment)
.commit();
break;
case 2:
musicService.removeNotification();
musicService.stopSelf();
MainActivity.this.finish();
}
}
loadSelection(0) is called in the onCreate of the MainActivity
Unlike given in the code, I have tried various modes of implementing the popBackStack() method but all of them lead to the same result. Just to add I don't want to implement a workaround since there are only 2 fragments since I am already working on adding new fragments.
try this,
call method .addToBackStack("returnFragment") while loading second fragment and remove it from first transaction.

Using the back button from a fragment in Android

I'm aiming for the following behavior.
When I am on my main activity,
If I navigate into fragment 1,
and from there, navigate into fragment 2,
then when I hit the phone's back button,
because I am on fragment 2 I am returned to the home screen, and not fragment 1.
If I had a separate button on the page, this behavior would be very easy, as I could just do:
Button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
FragmentManager fm = getFragmentManager();
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
});
I'm running into difficulties because I need to use the phone's own back button. I've read that the OnButtonPressed() event is only usable by an activity, not a fragment, and moving this kind of logic into the activity is proving difficult!
How can I achieve the behavior I'm after?
Just track the backstackcount and you can do whatever you want on the basis of count :
#Override
public void onBackPressed() {
manageBackStack();
}
private void manageBackStack() {
switch (getSupportFragmentManager().getBackStackEntryCount()) {
case 1:
//Do when count is 1
break;
case 2:
//Do when count is 2
break;
default:
finish();
}
}
Hope it will help :)
When you are adding the fragment you need to add the transaction to back stack. That means you want this transaction to be reversed when back button is pressed.
Please use the below code :
getSupportFragmentManager().beginTransaction()
.add(detailFragment, "detail")
// Add this transaction to the back stack
.addToBackStack()
.commit();
You can find more details in :
https://developer.android.com/training/implementing-navigation/temporal.html

Fragments and backstage sometimes get messed up

I have an activity with a container for fragments and a NavigationDrawer. If I select an item in the drawer, I call updatePage(index).
I also call updatePage(0) if I create the activity and the savedInstanceState == null to init my activity.
One fragment has a sub fragment and therefor it just replaces itself by the subfragment and adds the subfragment to the backstack, so that the user can navigate back to the previous fragment. In this fragment I call following code directly:
#Override
public void onClick(View view)
{
Event event = (Event)view.getTag();
FragmentManager fm = getActivity().getSupportFragmentManager();
GamesFragment f = new GamesFragment();
Bundle bundle = new Bundle();
bundle.putParcelable(GamesFragment.KEY_EVENT, event);
f.setArguments(bundle);
FragmentTransaction ft = fm.beginTransaction()
.replace(R.id.frame_container, f, f.getClass().getName())
.addToBackStack(null);
ft.commit();
}
Why does sometimes the removing of the old fragment not work? I get overlaying fragments, but only sometimes.
My activities updatePage function looks like following:
private void updatePage(int drawerSelection)
{
mDrawer.closeDrawer();
Fragment f = null;
FragmentManager fm = getSupportFragmentManager();
switch (drawerSelection)
{
case 0:
f = fm.findFragmentByTag(HomeFragment.class.getName());
if (f == null)
f = new HomeFragment();
break;
case 1:
f = fm.findFragmentByTag(EventFragment.class.getName());
if (f == null)
f = new EventFragment();
break;
default:
break;
}
if (f != null && !f.isAdded())
{
// SOLUTION:
// Backstack clearen
// fm.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.frame_container, f, f.getClass().getName());
ft.commit();
}
}
I saw such situation few times and I bet that it can happen after replacing with addToBackStack. Easiest fix is to add background to fragment layout. From android doc:
Note: When you remove or replace a fragment and add the transaction to the back stack, the fragment that is removed is stopped (not destroyed). If the user navigates back to restore the fragment, it restarts. If you do not add the transaction to the back stack, then the fragment is destroyed when removed or replaced.
This view is not redrawed entirely just overdrawed and if second fragment doesn't has background or view container redraw you will get effect as described. That's my theory :>. Sometimes Android documentation is not as clear as we would like it to be.
The problem is following use case:
Going to the EventFragment from the GameFragment pushes the "remove(EventFragment).add(GameFragment)" transaction to the backstack. If I now press the back button, this transaction will be undone and everything is fine. The backstack is empty again and everything works. BUT, if I don't press the back button, but change to another fragment through the menu, the backstack does still have the above mentioned transaction. Pressing back will now try to undo this transaction... It will just readd the EventFragment before the code in my menu click handler adds the fragment from the menu... This is how it could happen...
Easy solution, if I only want one backstack for every menu entry and want to delete the backstack, if I select another area of my app in the menu is, to clear the backstack before I go to another area through the menu...
So adding ' fm.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);' before replacing the the current fragment will solve the problem (I added this solution as a comment to my main post)

Skip some fragments onBackPressed

I am fairly new with android fragments so please bear with me.
I have a bunch of fragments using a single activity as host.
In my mind, my fragments are grouped by sections although they are still modular/reusable by code.
Consider this desired scenario:
Frag1 -> (Press Next) -> Frag2 -> (Press Next) -> Frag3 -> (Press Back) -> Frag1
After going through a series of fragments, I would like to skip some previous fragments (in this scenario, skip Frag 2) on pressing the back button.
However, in my current code, my problem is that even though it goes back to Frag1, Frag3 does not disappear from the screen. What happens is that both Frag1 and Frag3 becomes visible on top of each other.
Here are my relevant code snippets:
Code snippet for creating Frag1
#Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
// init the fragment (with a default fragment, not null)
Fragment fragment = PlaceholderFragment.newInstance(position + 1);
// Position number from navigation sidebar starts from 0.
// Since position starts from 0, add 1 to match section number
// as implemented in {#link #onSectionAttached()}
switch(position) {
case 0:
fragment = PlaceholderFragment.newInstance(position + 1);
break;
case 1: // Frag1 case
fragment = new AddPointsFragment().newInstance(position + 1, "");
break;
default:
break;
}
// update the main content by replacing fragments
FragmentManager fragmentManager = getFragmentManager();
// clear all fragments from previous section from the back stack
fragmentManager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
// replace all currently added fragments in container and replace with the new fragment
fragmentManager.beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
Code snippet for creating Frag2
public void onEnterButtonFragmentInteraction(int sectionNumber, String cardNo) {
// TODO: Add point for given card number
int points = 5; //sample points
AddPointsSuccessFragment addPointsSuccessFragment =
new AddPointsSuccessFragment().newInstance(sectionNumber, cardNo, points);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.container, addPointsSuccessFragment)
.addToBackStack(null)
.commit();
}
Code snippet for creating Frag3
public void onOkButtonFragmentInteraction(int sectionNumber, String cardNo, int points) {
RedeemRewardFragment redeemRewardFragment =
new RedeemRewardFragment().newInstance(sectionNumber, cardNo, points);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container, redeemRewardFragment);
fragmentTransaction.commit();
}
My current workaround for this is by adding .addToBackStack(null) in creating Frag3 and running this code
public void onBackButtonFragmentInteraction() {
this.onBackPressed(); // simulate pressing of activity back button
FragmentManager fragmentmanager = getFragmentManager();
fragmentmanager.popBackStack(); // pop Frag2 from back stack
}
right after calling the onBackPressed() method. Unfortunately, this workaround is ugly because because there is a split-second appearance of Frag2 before going to Frag1.
So the key to your solution here is this guy:
.addToBackStack(null)
Instead of null, you can pass in a String identifier for that particular transaction -- for instance, the class name of the Fragment is what we use (although that doesn't work if you have multiple instances of the same fragment on the backstack):
.addToBackStack(Fragment1.class.getName())
Then, if you wanted to get back to Fragment1 from Fragment3, just pop using the identifier of the next fragment, and pass the INCLUSIVE flag (which means it will also pop that next fragment that you specified):
getFragmentManager().popBackStack(
Fragment2.class.getName(),
FragmentManager.POP_BACK_STACK_INCLUSIVE);
Which will play your animations as expected, but as if the fragments in between were never there. The reason I suggest to use the next fragment is because you probably don't want your first fragment transaction on the back stack.
You could try this, it should work and doesnt give a split-second delay. Its not beautiful code though, and if somebody has a better way, please post.
1.Give a tag to your fragments.
transaction.add(R.id.main_activity_container, FirstFragment, "FirstFragment");
transaction.replace(R.id.main_activity_container, Second, "SECOND");
transaction.replace(R.id.main_activity_container, Third, "THIRD");
2.Modify your onBackPressed() in your frameActivity (activity) that "houses" your fragments.
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
int lastStack = getSupportFragmentManager().getBackStackEntryCount();
try {
//If the last fragment was named/tagged "three"
if (getSupportFragmentManager().getFragments().get(lastStack).getTag().equalsIgnoreCase("THIRD")){
getSupportFragmentManager().popBackStackImmediate();
getSupportFragmentManager().popBackStackImmediate();
//Get your first fragment that you loaded in the beginning.
Fragment first = getSupportFragmentManager().findFragmentByTag("FirstFragment");
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.main_activity_container, first);
transaction.commit();
return;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.onBackPressed();
}
When you display Frag2 use:
final FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.addToBackStack(FRAG_2);
fragmentTransaction.replace(containerID, frag2, FRAG2_TAG);
and on back press:
#Override
public void onBackPressed() {
final Frag2 frag2 = (Frag2)getSupportFragmentManager().findFragmentByTag(FRAG2_TAG);
if (frag2 != null && frag2.isVisible() && getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStackImmediate();
return;
}
}
This will prevent from frag2 to be displayed after onBackPressed() called.
Avoid using popBackStack() as this will results in frag2 lifecycle trigger (onCreate, onStart, onResume ...)

Problems with Android Fragment back stack

I've got a massive problem with the way the android fragment backstack seems to work and would be most grateful for any help that is offered.
Imagine you have 3 Fragments
[1] [2] [3]
I want the user to be able to navigate [1] > [2] > [3] but on the way back (pressing back button) [3] > [1].
As I would have imagined this would be accomplished by not calling addToBackStack(..) when creating the transaction that brings fragment [2] into the fragment holder defined in XML.
The reality of this seems as though that if I dont want [2] to appear again when user presses back button on [3], I must not call addToBackStack in the transaction that shows fragment [3]. This seems completely counter-intuitive (perhaps coming from the iOS world).
Anyway if i do it this way, when I go from [1] > [2] and press back I arrive back at [1] as expected.
If I go [1] > [2] > [3] and then press back I jump back to [1] (as expected).
Now the strange behavior happens when I try and jump to [2] again from [1]. First of all [3] is briefly displayed before [2] comes into view. If I press back at this point [3] is displayed, and if I press back once again the app exits.
Can anyone help me to understand whats going on here?
And here is the layout xml file for my main activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<fragment
android:id="#+id/headerFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
class="com.fragment_test.FragmentControls" >
<!-- Preview: layout=#layout/details -->
</fragment>
<FrameLayout
android:id="#+id/detailFragment"
android:layout_width="match_parent"
android:layout_height="fill_parent"
/>
Update
This is the code I'm using to build by nav heirarchy
Fragment frag;
FragmentTransaction transaction;
//Create The first fragment [1], add it to the view, BUT Dont add the transaction to the backstack
frag = new Fragment1();
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.detailFragment, frag);
transaction.commit();
//Create the second [2] fragment, add it to the view and add the transaction that replaces the first fragment to the backstack
frag = new Fragment2();
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.detailFragment, frag);
transaction.addToBackStack(null);
transaction.commit();
//Create third fragment, Dont add this transaction to the backstack, because we dont want to go back to [2]
frag = new Fragment3();
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.detailFragment, frag);
transaction.commit();
//END OF SETUP CODE-------------------------
//NOW:
//Press back once and then issue the following code:
frag = new Fragment2();
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.detailFragment, frag);
transaction.addToBackStack(null);
transaction.commit();
//Now press back again and you end up at fragment [3] not [1]
Many thanks
Explanation: on what's going on here?
If we keep in mind that .replace() is equal with .remove().add() that we know by the documentation:
Replace an existing fragment that was added to a container. This is essentially the same as calling remove(Fragment) for all currently added fragments that were added with the same containerViewId and then add(int, Fragment, String) with the same arguments given here.
then what's happening is like this (I'm adding numbers to the frag to make it more clear):
// transaction.replace(R.id.detailFragment, frag1);
Transaction.remove(null).add(frag1) // frag1 on view
// transaction.replace(R.id.detailFragment, frag2).addToBackStack(null);
Transaction.remove(frag1).add(frag2).addToBackStack(null) // frag2 on view
// transaction.replace(R.id.detailFragment, frag3);
Transaction.remove(frag2).add(frag3) // frag3 on view
(here all misleading stuff starts to happen)
Remember that .addToBackStack() is saving only transaction not the fragment as itself! So now we have frag3 on the layout:
< press back button >
// System pops the back stack and find the following saved back entry to be reversed:
// [Transaction.remove(frag1).add(frag2)]
// so the system makes that transaction backward!!!
// tries to remove frag2 (is not there, so it ignores) and re-add(frag1)
// make notice that system doesn't realise that there's a frag3 and does nothing with it
// so it still there attached to view
Transaction.remove(null).add(frag1) //frag1, frag3 on view (OVERLAPPING)
// transaction.replace(R.id.detailFragment, frag2).addToBackStack(null);
Transaction.remove(frag3).add(frag2).addToBackStack(null) //frag2 on view
< press back button >
// system makes saved transaction backward
Transaction.remove(frag2).add(frag3) //frag3 on view
< press back button >
// no more entries in BackStack
< app exits >
Possible solution
Consider implementing FragmentManager.BackStackChangedListener to watch for changes in the back stack and apply your logic in onBackStackChanged() methode:
Trace a count of transaction;
Check particular transaction by name FragmentTransaction.addToBackStack(String name);
Etc.
It seems as though fragment [3] is not removed from the view when back is pressed so you have to do it manually!
First of all, don't use replace() but instead use remove and add separately. It seems as though replace() doesn't work properly.
The next part to this is overriding the onKeyDown method and remove the current fragment every time the back button is pressed.
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_BACK)
{
if (getSupportFragmentManager().getBackStackEntryCount() == 0)
{
this.finish();
return false;
}
else
{
getSupportFragmentManager().popBackStack();
removeCurrentFragment();
return false;
}
}
return super.onKeyDown(keyCode, event);
}
public void removeCurrentFragment()
{
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
Fragment currentFrag = getSupportFragmentManager().findFragmentById(R.id.detailFragment);
String fragName = "NONE";
if (currentFrag!=null)
fragName = currentFrag.getClass().getSimpleName();
if (currentFrag != null)
transaction.remove(currentFrag);
transaction.commit();
}
First of all thanks #Arvis for an eye opening explanation.
I prefer different solution to the accepted answer here for this problem. I don't like messing with overriding back behavior any more than absolutely necessary and when I've tried adding and removing fragments on my own without default back stack poping when back button is pressed I found my self in fragment hell :) If you .add f2 over f1 when you remove it f1 won't call any of callback methods like onResume, onStart etc. and that can be very unfortunate.
Anyhow this is how I do it:
Currently on display is only fragment f1.
f1 -> f2
Fragment2 f2 = new Fragment2();
this.getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.main_content,f2).addToBackStack(null).commit();
nothing out of the ordinary here. Than in fragment f2 this code takes you to fragment f3.
f2 -> f3
Fragment3 f3 = new Fragment3();
getActivity().getSupportFragmentManager().popBackStack();
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.main_content, f3).addToBackStack(null).commit();
I'm not sure by reading docs if this should work, this poping transaction method is said to be asynchronous, and maybe a better way would be to call popBackStackImmediate(). But as far I can tell on my devices it's working flawlessly.
The said alternative would be:
final FragmentActivity activity = getActivity();
activity.getSupportFragmentManager().popBackStackImmediate();
activity.getSupportFragmentManager().beginTransaction().replace(R.id.main_content, f3).addToBackStack(null).commit();
Here there will actually be brief going back to f1 beofre moving on to f3, so a slight glitch there.
This is actually all you have to do, no need to override back stack behavior...
I know it's a old quetion but i got the same problem and fix it like this:
First, Add Fragment1 to BackStack with a name (e.g "Frag1"):
frag = new Fragment1();
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.detailFragment, frag);
transaction.addToBackStack("Frag1");
transaction.commit();
And then, Whenever you want to go back to Fragment1 (even after adding 10 fragments above it), just call popBackStackImmediate with the name:
getSupportFragmentManager().popBackStackImmediate("Frag1", 0);
Hope it will help someone :)
After #Arvis reply i decided to dig even deeper and I've written a tech article about this here: http://www.andreabaccega.com/blog/2015/08/16/how-to-avoid-fragments-overlapping-due-to-backstack-nightmare-in-android/
For the lazy developers around. My solution consists in always adding the transactions to the backstack and perform an extra FragmentManager.popBackStackImmediate() when needed (automatically).
The code is very few lines of code and, in my example, I wanted to skip from C to A without jumping back to "B" if the user didn't went deeper in the backstack (ex from C navigates to D).
Hence the code attached would work as follow
A -> B -> C (back) -> A
&
A -> B -> C -> D (back) -> C (back) -> B (back) -> A
where
fm.beginTransaction().replace(R.id.content, new CFragment()).commit()
were issued from "B" to "C" as in the question.
Ok,Ok here is the code :)
public static void performNoBackStackTransaction(FragmentManager fragmentManager, String tag, Fragment fragment) {
final int newBackStackLength = fragmentManager.getBackStackEntryCount() +1;
fragmentManager.beginTransaction()
.replace(R.id.content, fragment, tag)
.addToBackStack(tag)
.commit();
fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
int nowCount = fragmentManager.getBackStackEntryCount();
if (newBackStackLength != nowCount) {
// we don't really care if going back or forward. we already performed the logic here.
fragmentManager.removeOnBackStackChangedListener(this);
if ( newBackStackLength > nowCount ) { // user pressed back
fragmentManager.popBackStackImmediate();
}
}
}
});
}
If you are Struggling with addToBackStack() & popBackStack() then simply use
FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, new HomeFragment(), "Home");
ft.commit();`
In your Activity In OnBackPressed() find out fargment by tag and then do your stuff
Fragment home = getSupportFragmentManager().findFragmentByTag("Home");
if (home instanceof HomeFragment && home.isVisible()) {
// do you stuff
}
For more Information https://github.com/DattaHujare/NavigationDrawer
I never use addToBackStack() for handling fragment.
I think, when I read your story that [3] is also on the backstack. This explains why you see it flashing up.
Solution would be to never set [3] on the stack.
I had a similar issue where I had 3 consecutive fragments in the same Activity [M1.F0]->[M1.F1]->[M1.F2] followed by a call to a new Activity[M2]. If the user pressed a button in [M2] I wanted to return to [M1,F1] instead of [M1,F2] which is what back press behavior already did.
In order to accomplish this I remove [M1,F2], call show on [M1,F1], commit the transaction, and then add [M1,F2] back by calling it with hide. This removed the extra back press that would have otherwise been left behind.
// Remove [M1.F2] to avoid having an extra entry on back press when returning from M2
final FragmentTransaction ftA = fm.beginTransaction();
ftA.remove(M1F2Fragment);
ftA.show(M1F1Fragment);
ftA.commit();
final FragmentTransaction ftB = fm.beginTransaction();
ftB.hide(M1F2Fragment);
ftB.commit();
Hi
After doing this code: I'm not able to see value of Fragment2 on pressing Back Key.
My Code:
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.frame, f1);
ft.remove(f1);
ft.add(R.id.frame, f2);
ft.addToBackStack(null);
ft.remove(f2);
ft.add(R.id.frame, f3);
ft.commit();
#Override
public boolean onKeyDown(int keyCode, KeyEvent event){
if(keyCode == KeyEvent.KEYCODE_BACK){
Fragment currentFrag = getFragmentManager().findFragmentById(R.id.frame);
FragmentTransaction transaction = getFragmentManager().beginTransaction();
if(currentFrag != null){
String name = currentFrag.getClass().getName();
}
if(getFragmentManager().getBackStackEntryCount() == 0){
}
else{
getFragmentManager().popBackStack();
removeCurrentFragment();
}
}
return super.onKeyDown(keyCode, event);
}
public void removeCurrentFragment()
{
FragmentTransaction transaction = getFragmentManager().beginTransaction();
Fragment currentFrag = getFragmentManager().findFragmentById(R.id.frame);
if(currentFrag != null){
transaction.remove(currentFrag);
}
transaction.commit();
}
executePendingTransactions() , commitNow() not worked (
Worked in androidx (jetpack).
private final FragmentManager fragmentManager = getSupportFragmentManager();
public void removeFragment(FragmentTag tag) {
Fragment fragmentRemove = fragmentManager.findFragmentByTag(tag.toString());
if (fragmentRemove != null) {
fragmentManager.beginTransaction()
.remove(fragmentRemove)
.commit();
// fix by #Ogbe
fragmentManager.popBackStackImmediate(tag.toString(),
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}

Categories

Resources