262

Say I have an activity that has fragments added programmatically:

private void animateToFragment(Fragment newFragment, String tag) {
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container, newFragment, tag);
    ft.addToBackStack(null);
    ft.commit();
}

What is the best way to return to the previous fragment that was visible?

I found Trigger back-button functionality on button click in Android but I'm thinking simulating a back key event isn't the right way to go about it (and I can't get it to work either):

dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));

Calling finish() just closes the activity which I'm not interested in.

Is there a better way to go about this?

Community
  • 1
  • 1
Aske B.
  • 6,419
  • 8
  • 35
  • 62

15 Answers15

405

Look at the getFragmentManager().popBackStack() methods (there are several to choose from)

http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack()

stuckless
  • 6,515
  • 2
  • 19
  • 27
  • 105
    `getFragmentManager().popBackStackImmediate();` did the trick. Thanks. – Aske B. Jun 02 '12 at 15:52
  • 1
    Where would I put this method though? In my tab listener? – rasen58 Dec 28 '12 at 21:17
  • 2
    without seeing the code, it's hard to say... but it should go in the section of code that is executed when you want to "close" the current fragment and return to the previous fragment. – stuckless Dec 29 '12 at 14:33
  • 2
    what about getSupportFragmentManager() – ViliusK Apr 10 '13 at 05:59
  • 1
    @alicanbatur yes you need to use addTOBackStack(). – Abhijit Chakra Jan 30 '14 at 09:36
  • What if we want to go to a fragment second or third previous. I visited fragments A->B->C->D and I want to go back to A or B from D? – Gokhan Arik Mar 27 '15 at 17:36
  • use popBackStack("A", flags) (see http://developer.android.com/reference/android/app/FragmentManager.html#popBackStackImmediate(int, int)) – stuckless Mar 28 '15 at 19:04
  • 6
    Don't forget to add "addToBackStack("tag")" in your code. "fragmentManager.beginTransaction().replace(R.id.content_frame,fragment).addToBackStack("tag").commit();" if you write addToBackStack(null) , it will handle it by itself but if you give a tag , you should handle it manually. – Khaled Saifullah Dec 08 '15 at 11:14
  • Not seems works. in 2016, into setNavigationOnClickListener not works. –  Mar 09 '16 at 11:45
  • `popBackStackImmediate` is slower than `popBackStack` in order to avoid performance issues use `popBackStack` where ever possible. – Faisal Naseer Apr 05 '18 at 07:45
  • 1
    the answer is now deprecated, you should use `getSupportFragmentManager().popBackStack()` – Alberto M Jun 12 '20 at 07:48
  • This sends me back to the first fragment. – John Glen Sep 27 '20 at 14:38
  • 1
    in kotlin you should use `supportFragmentManager().popBackStack()` – acmpo6ou Oct 04 '20 at 10:33
  • 1
    Note that if you're using navigation, this will work in getting you back but if you then try to navigate to the fragment that you popped, you'll encounter an error about not being able to navigate from the current destination. Instead, use `findNavController().navigateUp()`. – Kraigolas Nov 05 '20 at 22:23
141

To elaborate on the other answers provided, this is my solution (placed in an Activity):

@Override
public void onBackPressed(){
    FragmentManager fm = getFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        Log.i("MainActivity", "popping backstack");
        fm.popBackStack();
    } else {
        Log.i("MainActivity", "nothing on backstack, calling super");
        super.onBackPressed();  
    }
}
Kaidul
  • 15,409
  • 15
  • 81
  • 150
Kyle Falconer
  • 8,302
  • 6
  • 48
  • 68
  • 5
    and why is that happening. In fragment example http://developer.android.com/training/basics/fragments/index.html they are not overiding onbackpressed event and yet they are able to backstack fragment. I have used trasaction.addToBackStack(null); but nothing happens. Can you explain why ? – Murtaza Khursheed Hussain Nov 02 '13 at 15:08
  • @MurtazaHussain you should probably ask a new question if you want help with this. It's a little hard to see what's going on without looking at more code. – Kyle Falconer Nov 03 '13 at 15:24
  • 3
    In my case I had to do `fm.getBackStackEntryCount() > 1` in order to call the activity back when there is only the first fragment in the stack. – Facundo Olano Jul 24 '15 at 16:38
  • 3
    Android already do this for you: _"When there are FragmentTransaction objects on the back stack and the user presses the Back button, the FragmentManager pops the most recent transaction off the back stack and performs the reverse action (such as removing a fragment if the transaction added it)."_ [(Source)](https://developer.android.com/training/implementing-navigation/temporal.html) – artkoenig Oct 15 '16 at 10:58
38

When we are updating/add the fragments,

Should Include the .addToBackStack().

getSupportFragmentManager().beginTransaction()
    .add(detailFragment, "detail") // Add this transaction to the back stack (name is an optional name for this back stack state, or null).
    .addToBackStack(null)
    .commit();

After that if we give the getFragments.popBackStackImmediate() will return true if we add/update the fragments, and move back to the current screen.

Adeel
  • 2,901
  • 7
  • 24
  • 34
Jabeer
  • 879
  • 1
  • 8
  • 13
26

Android Navigation architecture component.

The following code works for me:

findNavController().popBackStack()
Yogesh Nikam Patil
  • 1,192
  • 13
  • 18
  • This method comes in handy when you are using a custom designed toolbar. Works like a charm. – karan_for_you Feb 10 '21 at 17:25
  • 2
    If you are using the navController I think you have to use this method - I first tried the fragment manager (the answer above) and got a crash when later trying to navigate using navController. – Andy Weinstein Feb 23 '21 at 07:22
18

These answers does not work if i don't have addToBackStack() added to my fragment transaction but, you can use:

getActivity().onBackPressed();

from your any fragment to go back one step;

Biplob Das
  • 2,818
  • 21
  • 13
10

Add those line to your onBackPressed() Method. popBackStackImmediate() method will get you back to the previous fragment if you have any fragment on back stack `

if(getFragmentManager().getBackStackEntryCount() > 0){
     getFragmentManager().popBackStackImmediate();
}
else{
    super.onBackPressed();
}

`

Avijit Biswas
  • 425
  • 5
  • 11
5

This solution works perfectly for bottom bar based fragment navigation when you want to close the app when back pressed in primary fragment.

On the other hand when you are opening the secondary fragment (fragment in fragment) which is defined as "DetailedPizza" in my code it will return the previous state of primary fragment. Cheers !

Inside activities on back pressed put this:

Fragment home = getSupportFragmentManager().findFragmentByTag("DetailedPizza");

if (home instanceof FragmentDetailedPizza && home.isVisible()) {
    if (getFragmentManager().getBackStackEntryCount() != 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
} else {
    //Primary fragment
    moveTaskToBack(true);
}

And launch the other fragment like this:

Fragment someFragment = new FragmentDetailedPizza();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, someFragment, "DetailedPizza");
transaction.addToBackStack("DetailedPizza");
transaction.commit();
Andrew Trubin
  • 143
  • 1
  • 1
  • 11
Giedrius Šlikas
  • 1,073
  • 12
  • 12
5

Kotlin Answer

  1. First, call Fragment Manager.
  2. After, to use onBackPressed() method.

Coding in Android Studio 4.0 with Kotlin:

fragmentManager?.popBackStack()
ChrisF
  • 134,786
  • 31
  • 255
  • 325
canerkaseler
  • 6,204
  • 45
  • 38
2

Programmatically go back to the previous fragment using following code.

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();
2

To make that fragment come again, just add that fragment to backstack which you want to come on back pressed, Eg:

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Fragment fragment = new LoginFragment();
        //replacing the fragment
        if (fragment != null) {
            FragmentTransaction ft = ((FragmentActivity)getContext()).getSupportFragmentManager().beginTransaction();
            ft.replace(R.id.content_frame, fragment);
            ft.addToBackStack("SignupFragment");
            ft.commit();
        }
    }
});

In the above case, I am opening LoginFragment when Button button is pressed, right now the user is in SignupFragment. So if addToBackStack(TAG) is called, where TAG = "SignupFragment", then when back button is pressed in LoginFragment, we come back to SignUpFragment.

Happy Coding!

Bugs Buggy
  • 1,514
  • 19
  • 39
Saurabh Singh
  • 1,241
  • 13
  • 11
2

By adding fragment_tran.addToBackStack(null) on last fragment, I am able to do come back on last fragment.

adding new fragment:

view.findViewById(R.id.changepass).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.container, new ChangePassword());
            transaction.addToBackStack(null);
            transaction.commit();
        }
    });
double-beep
  • 5,031
  • 17
  • 33
  • 41
2

Following Kotlin code useful to me

1. Added in Simple Activity class with multiple fragments used

override fun onBackPressed() {
    if (supportFragmentManager.backStackEntryCount > 0) {
        Log.i(TAG, "=============onBackPressed - Popping backstack====")
        supportFragmentManager.popBackStack()
    } else {
        Log.i(TAG, "=============onBackPressed called because nothing on backstack====")
        super.onBackPressed()
    }
}

2. Added in BottomNavigationView Activity class with multiple fragments used

override fun onBackPressed() {

    Log.e(TAG, "=============onBackPressed")
    val navController = findNavController(R.id.nav_host_fragment)
    when (navController.currentDestination!!.id) {
        R.id.navigation_comments, R.id.navigation_my_posts -> {
            menuItemPosition = 0
            navController.navigate(R.id.navigation_home)
            Log.i(TAG, "=============onBackPressed - Popping backstack with First fragment ====")
        }
        else -> {
            Log.i(TAG, "=============onBackPressed called because nothing on backstack====")
            super.onBackPressed()
        }
    }
}
Pratik Dodiya
  • 2,337
  • 1
  • 19
  • 12
2
getActivity().getSupportFragmentManager().popBackStackImmediate();

OR

 getActivity().onBackPressed();
Masoud Siahkali
  • 5,100
  • 1
  • 29
  • 18
  • 4
    Please read [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer). While this code block may answer the OP's question, this answer would be much more useful if you explain how this code is different from the code in the question, what you've changed, why you've changed it and why that solves the problem without introducing others. – Saeed Zhiany Jun 27 '22 at 07:15
1

I came here looking or the same idea, and in the meantime i came up with own, which I believe is not that bad and works if with ViewPager.

So what I did, is to override the onBackPressed method in the parent activity that holds the viewPager, and set it to always go back minus 1 position until it reaches the first fragment, then closes the activity.

@Override
public void onBackPressed() {
    if(viewPager.getCurrentItem()>0){
        viewPager.setCurrentItem(viewPager.getCurrentItem()-1);
    } else {
        super.onBackPressed();
        this.close();
    }
}

private void close(){
    this.finish();
}

This might have a downfalls, like it only goes back one way left each time, so it might not work great if there are tabs and you switch positions with fragments skipped, ( going from 0 to 2, and then pressing back would put you on 1, instead of 0)

For my case tho, with 2 fragments in viewPager without tabs, it does the job nicely.

  • Similar question is already answered. https://stackoverflow.com/questions/10863572/programmatically-go-back-to-the-previous-fragment-in-the-backstack – AtifSayings Mar 07 '20 at 03:50
0

Try below code:

@Override
    public void onBackPressed() {
        Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.container);
        if (myFragment != null && myFragment instanceof StepOneFragment) {
            finish();
        } else {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                getSupportFragmentManager().popBackStack();
            } else {
                super.onBackPressed();
            }
        }
    }
Nagama Inamdar
  • 2,851
  • 22
  • 39
  • 48
adarsh
  • 403
  • 3
  • 8