¿Cómo implementar onBackPressed () en Fragments?

¿Hay alguna manera en la que podamos implementar onBackPressed() en Android Fragment similar a la forma en que implementamos en Android Activity?

Como el ciclo de vida de Fragment no tiene onBackPressed() . ¿Hay algún otro método alternativo para sobrepasar onBackPressed() en los fragmentos de Android 3.0?

Solucioné de esta manera la anulación onBackPressed en la Actividad. Todos los FragmentTransaction son addToBackStack antes de confirmar:

 @Override public void onBackPressed() { int count = getFragmentManager().getBackStackEntryCount(); if (count == 0) { super.onBackPressed(); //additional code } else { getFragmentManager().popBackStack(); } } 

Según la respuesta de @HaMMeRed, aquí está el pseudocódigo, ¿cómo debería funcionar? Digamos que su actividad principal se llama BaseActivity que tiene fragmentos secundarios (como en el ejemplo de SlidingMenu lib). Estos son los pasos:

Primero, necesitamos crear una interfaz y clase que implemente su interfaz para tener un método genérico

  1. Crear interfaz de clase OnBackPressedListener

     public interface OnBackPressedListener { public void doBack(); } 
  2. Crear clase que implemente las habilidades de OnBackPressedListener

     public class BaseBackPressedListener implements OnBackPressedListener { private final FragmentActivity activity; public BaseBackPressedListener(FragmentActivity activity) { this.activity = activity; } @Override public void doBack() { activity.getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); } } 
  3. Desde ahora, trabajaremos en nuestro código BaseActivity y sus fragmentos

  4. Crea un oyente privado encima de tu clase BaseActivity

     protected OnBackPressedListener onBackPressedListener; 
  5. crear un método para establecer el oyente en BaseActivity

     public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) { this.onBackPressedListener = onBackPressedListener; } 
  6. anular onBackPressed implementar algo así

     @Override public void onBackPressed() { if (onBackPressedListener != null) onBackPressedListener.doBack(); else super.onBackPressed(); 
  7. en tu fragmento en onCreateView deberías agregar nuestro oyente

     @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { activity = getActivity(); ((BaseActivity)activity).setOnBackPressedListener(new BaseBackPressedListener(activity)); View view = ... ; //stuff with view return view; } 

Voila, ahora cuando vuelves a hacer clic en fragmento debes ver tu método personalizado en la parte posterior.

Esto funcionó para mí: https://stackoverflow.com/a/27145007/3934111

 @Override public void onResume() { super.onResume(); if(getView() == null){ return; } getView().setFocusableInTouchMode(true); getView().requestFocus(); getView().setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){ // handle back button's click listener return true; } return false; } }); } 

Si desea ese tipo de funcionalidad, deberá anularla en su actividad y luego agregar una interfaz YourBackPressed a todos sus fragmentos, a la que llame en el fragmento relevante siempre que se presione el botón Atrás.

Editar: me gustaría agregar mi respuesta anterior.

Si tuviera que hacer esto hoy, usaría una transmisión, o posiblemente una transmisión ordenada, si esperaba que otros paneles se actualizaran al unísono al panel de contenido maestro / principal.

LocalBroadcastManager en la Biblioteca de soporte puede ayudar con esto, y usted simplemente envía la transmisión onBackPressed y se suscribe en sus fragmentos que le importan. Creo que Messaging es una implementación más desacoplada y se escalaría mejor, por lo que sería mi recomendación de implementación oficial ahora. Simplemente use la acción de Intent como filtro para su mensaje. envíe su ACTION_BACK_PRESSED recién creado, envíelo desde su actividad y escúchelo en los fragmentos relevantes.

Nada de eso es fácil de implementar ni funcionará de manera óptima.

Los fragmentos tienen una llamada a método enDetach que hará el trabajo.

 @Override public void onDetach() { super.onDetach(); PUT YOUR CODE HERE } 

ESTO HARÁ EL TRABAJO.

Creo que la mejor solución es Crear interfaz simple:

 public interface IOnBackPressed { /** * If you return true the back press will not be taken into account, otherwise the activity will act naturally * @return true if your processing has priority if not false */ boolean onBackPressed(); } 

Y en tu actividad

 public class MyActivity extends Activity { @Override public void onBackPressed() { Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_container); if (!(fragment instanceof IOnBackPressed) || !((IOnBackPressed) fragment).onBackPressed()) { super.onBackPressed(); } } ... } 

Finalmente en tu Fragmento:

 public class MyFragment extends Fragment implements IOnBackPressed{ @Override public boolean onBackPressed() { if (myCondition) { //action not popBackStack return true; } else { return false; } } } 

Simplemente agrega addToBackStack mientras haces la transición entre tus fragmentos como se muestra a continuación:

 fragmentManager.beginTransaction().replace(R.id.content_frame,fragment).addToBackStack("tag").commit(); 

si escribe addToBackStack(null) , lo manejará solo, pero si le da una etiqueta, debe manejarlo manualmente.

ya que esta pregunta y algunas de las respuestas tienen más de cinco años, permítanme compartir mi solución. Este es un seguimiento y modernización de la respuesta de @oyenigun

ACTUALIZACIÓN: Al final de este artículo, agregué una implementación alternativa usando una extensión Fragmento abstracta que no involucrará la Actividad en absoluto, que sería útil para cualquier persona con una jerarquía de fragmentos más compleja que involucre fragmentos nesteds que requieran un comportamiento diferente.

Necesitaba implementar esto porque algunos de los fragmentos que uso tienen vistas más pequeñas que me gustaría descartar con el botón Atrás, como pequeñas vistas de información que aparecen, etc., pero esto es bueno para cualquiera que necesite anular el comportamiento de el botón de atrás dentro de los fragmentos.

Primero, define una interfaz

 public interface Backable { boolean onBackPressed(); } 

Esta interfaz, a la que llamo Backable (me Backable convenciones de nomenclatura), tiene un único método onBackPressed() que debe devolver un valor boolean . Necesitamos forzar un valor booleano porque necesitaremos saber si presionar el botón Atrás ha “absorbido” el evento posterior. Devolver true significa que sí lo ha hecho, y no se necesita ninguna otra acción, de lo contrario, false dice que la acción de retroceso predeterminada aún debe tener lugar. Esta interfaz debe ser su propio archivo (preferentemente en un paquete separado denominado interfaces ). Recuerde, separar sus clases en paquetes es una buena práctica.

Segundo, encuentra el fragmento superior

Creé un método que devuelve el último objeto Fragment en la stack posterior. Uso tags … si usa ID, haga los cambios necesarios. Tengo este método estático en una clase de utilidad que trata con los estados de navegación, etc. … pero, por supuesto, colóquelo donde más le convenga. Para la edificación, he puesto el mío en una clase llamada NavUtils .

 public static Fragment getCurrentFragment(Activity activity) { FragmentManager fragmentManager = activity.getFragmentManager(); if (fragmentManager.getBackStackEntryCount() > 0) { String lastFragmentName = fragmentManager.getBackStackEntryAt( fragmentManager.getBackStackEntryCount() - 1).getName(); return fragmentManager.findFragmentByTag(lastFragmentName); } return null; } 

Asegúrese de que el recuento de la stack posterior sea mayor que 0, de lo contrario, podría ArrayOutOfBoundsException una ArrayOutOfBoundsException en el tiempo de ejecución. Si no es mayor que 0, devuelve nulo. Comprobaremos si hay un valor nulo después …

En tercer lugar, implementar en un fragmento

Implemente la interfaz de Backable en cualquier fragmento donde necesite anular el comportamiento del botón de retroceso. Agrega el método de implementación.

 public class SomeFragment extends Fragment implements FragmentManager.OnBackStackChangedListener, Backable { ... @Override public boolean onBackPressed() { // Logic here... if (backButtonShouldNotGoBack) { whateverMethodYouNeed(); return true; } return false; } } 

En la onBackPressed() , ponga la lógica que necesite. Si desea que el botón Atrás no muestre la stack (el comportamiento predeterminado), devuelva true , que su evento reverso haya sido absorbido. De lo contrario, devuelve falso.

Por último, en tu Actividad …

Reemplace el método onBackPressed() y agregue esta lógica a él:

 @Override public void onBackPressed() { // Get the current fragment using the method from the second step above... Fragment currentFragment = NavUtils.getCurrentFragment(this); // Determine whether or not this fragment implements Backable // Do a null check just to be safe if (currentFragment != null && currentFragment instanceof Backable) { if (((Backable) currentFragment).onBackPressed()) { // If the onBackPressed override in your fragment // did absorb the back event (returned true), return return; } else { // Otherwise, call the super method for the default behavior super.onBackPressed(); } } // Any other logic needed... // call super method to be sure the back button does its thing... super.onBackPressed(); } 

Obtenemos el fragmento actual en la stack posterior, luego hacemos una comprobación nula y determinamos si implementa nuestra interfaz Backable . Si lo hace, determine si el evento fue absorbido. Si es así, hemos terminado con onBackPressed() y podemos devolverlo. De lo contrario, trátelo como una contrapresión normal y llame al método súper.

Segunda opción para no involucrar la actividad

En ocasiones, no desea que la Actividad maneje esto en absoluto, y necesita manejarlo directamente dentro del fragmento. ¿Pero quién dice que no puedes tener Fragmentos con una API de retroceso? Simplemente extienda su fragmento a una nueva clase.

Cree una clase abstracta que amplíe Fragment e implemente la interfaz View.OnKeyListner

 import android.app.Fragment; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; public abstract class BackableFragment extends Fragment implements View.OnKeyListener { @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); view.setFocusableInTouchMode(true); view.requestFocus(); view.setOnKeyListener(this); } @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP) { if (keyCode == KeyEvent.KEYCODE_BACK) { onBackButtonPressed(); return true; } } return false; } public abstract void onBackButtonPressed(); } 

Como puede ver, cualquier fragmento que extienda BackableFragment automáticamente capturará clics retrospectivos utilizando la interfaz View.OnKeyListener . Simplemente llame al onBackButtonPressed() abstracto onBackButtonPressed() desde el método onBackButtonPressed() implementado utilizando la lógica estándar para discernir la pulsación de un botón Atrás. Si necesita registrar clics clave que no sean el botón Atrás, solo asegúrese de llamar al método super cuando anule onKey() en su fragmento, de lo contrario, anulará el comportamiento en la abstracción.

Simple de usar, simplemente extienda e implemente:

 public class FragmentChannels extends BackableFragment { ... @Override public void onBackButtonPressed() { if (doTheThingRequiringBackButtonOverride) { // do the thing } else { getActivity().onBackPressed(); } } ... } 

Como el método onBackButtonPressed() en la onBackButtonPressed() es abstracto, una vez que lo amplíe debe implementar onBackButtonPressed() . Vuelve void porque solo necesita realizar una acción dentro de la clase de fragmento, y no necesita retransmitir la absorción de la imprenta a la Actividad. Asegúrate de llamar al onBackPressed() Activity onBackPressed() si lo que estás haciendo con el botón Atrás no requiere manejo, de lo contrario, el botón Atrás estará desactivado … ¡y no quieres eso!

Advertencias Como puede ver, esto establece el oyente clave para la vista raíz del fragmento, y necesitaremos enfocarlo. Si hay textos de edición involucrados (o cualquier otra vista que roba el enfoque) en su fragmento que amplíe esta clase (u otros fragmentos internos o vistas que tengan el mismo), deberá manejarlo por separado. Hay un buen artículo sobre la extensión de un EditText para perder el foco en una operación de retroceso.

Espero que alguien encuentre esto útil. Feliz encoding.

La solución es simple:

1) Si tienes una clase de fragmento de base que extienden todos los fragmentos, entonces agrega este código a su clase, de lo contrario crea una clase de fragmento de base

  /* * called when on back pressed to the current fragment that is returned */ public void onBackPressed() { // add code in super class when override } 

2) En su clase de actividad, anule onBackPressed de la siguiente manera:

 private BaseFragment _currentFragment; @Override public void onBackPressed() { super.onBackPressed(); _currentFragment.onBackPressed(); } 

3) En tu clase Fragmento, agrega tu código deseado:

  @Override public void onBackPressed() { setUpTitle(); } 

Bueno, lo hice así, y funciona para mí

Interfaz simple

FragmentOnBackClickInterface.java

 public interface FragmentOnBackClickInterface { void onClick(); } 

Ejemplo de implementación

MyFragment.java

 public class MyFragment extends Fragment implements FragmentOnBackClickInterface { // other stuff public void onClick() { // what you want to call onBackPressed? } 

luego, solo anula la actividad de Activar en la actividad

  @Override public void onBackPressed() { int count = getSupportFragmentManager().getBackStackEntryCount(); List frags = getSupportFragmentManager().getFragments(); Fragment lastFrag = getLastNotNull(frags); //nothing else in back stack || nothing in back stack is instance of our interface if (count == 0 || !(lastFrag instanceof FragmentOnBackClickInterface)) { super.onBackPressed(); } else { ((FragmentOnBackClickInterface) lastFrag).onClick(); } } private Fragment getLastNotNull(List list){ for (int i= list.size()-1;i>=0;i--){ Fragment frag = list.get(i); if (frag != null){ return frag; } } return null; } 

onBackPressed() causa que el Fragmento se separe de la Actividad.

De acuerdo con la respuesta de @Sterling Diaz, creo que tiene razón. PERO alguna situación será incorrecta. (por ejemplo, girar la pantalla)

Entonces, creo que podríamos detectar si isRemoving() logra los objectives.

Puede escribirlo en onDetach() o onDestroyView() . Eso es trabajo.

 @Override public void onDetach() { super.onDetach(); if(isRemoving()){ // onBackPressed() } } @Override public void onDestroyView() { super.onDestroyView(); if(isRemoving()){ // onBackPressed() } } 

Debe agregar la interfaz a su proyecto como a continuación;

 public interface OnBackPressed { void onBackPressed(); } 

Y luego, debes implementar esta interfaz en tu fragmento;

 public class SampleFragment extends Fragment implements OnBackPressed { @Override public void onBackPressed() { //on Back Pressed } } 

Y puede activar este evento onBackPressed en sus actividades en el evento BackPressed como se muestra a continuación;

 public class MainActivity extends AppCompatActivity { @Override public void onBackPressed() { Fragment currentFragment = getSupportFragmentManager().getFragments().get(getSupportFragmentManager().getBackStackEntryCount() - 1); if (currentFragment instanceof OnBackPressed) { ((OnBackPressed) currentFragment).onBackPressed(); } super.onBackPressed(); } } 

Si usa EventBus, probablemente sea una solución mucho más simple:

En tu Fragmento:

 @Override public void onAttach(Activity activity) { super.onAttach(activity); EventBus.getDefault().register(this); } @Override public void onDetach() { super.onDetach(); EventBus.getDefault().unregister(this); } // This method will be called when a MessageEvent is posted public void onEvent(BackPressedMessage type){ getSupportFragmentManager().popBackStack(); } 

y en tu clase de Actividad puedes definir:

 @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { EventBus.getDefault().unregister(this); super.onStop(); } // This method will be called when a MessageEvent is posted public void onEvent(BackPressedMessage type){ super.onBackPressed(); } @Override public void onBackPressed() { EventBus.getDefault().post(new BackPressedMessage(true)); } 

BackPressedMessage.java es solo un objeto POJO

Esto es súper limpio y no hay problemas de interfaz / implementación.

¿Qué hay de usar onDestroyView ()?

 @Override public void onDestroyView() { super.onDestroyView(); } 

Este es solo un pequeño código que hará el truco:

  getActivity().onBackPressed(); 

Espero que ayude a alguien 🙂

Respuesta muy breve y dulce:

 getActivity().onBackPressed(); 

Explicación de todo el escenario de mi caso:

Tengo FragmentA en MainActivity, estoy abriendo FragmentB de FragmentA (FragmentB es un fragmento nested o hijo de FragmentA)

  Fragment duedateFrag = new FragmentB(); FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.container_body, duedateFrag); ft.addToBackStack(null); ft.commit(); 

Ahora, si quieres ir a FragmentA desde FragmentB puedes simplemente poner getActivity().onBackPressed(); en FragmentB.

esta es mi solución:

en MyActivity.java:

 public interface OnBackClickListener { boolean onBackClick(); } private OnBackClickListener onBackClickListener; public void setOnBackClickListener(OnBackClickListener onBackClickListener) { this.onBackClickListener = onBackClickListener; } @Override public void onBackPressed() { if (onBackClickListener != null && onBackClickListener.onBackClick()) { return; } super.onBackPressed(); } 

y en Fragmento:

 ((MyActivity) getActivity()).setOnBackClickListener(new MyActivity.OnBackClickListener() { @Override public boolean onBackClick() { if (condition) { return false; } // some codes return true; } }); 

No implemente el método ft.addToBackStack () para que cuando presione el botón Atrás, su actividad finalice.

 proAddAccount = new ProfileAddAccount(); FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.fragment_container, proAddAccount); //fragmentTransaction.addToBackStack(null); fragmentTransaction.commit(); 

Solo sigue estos pasos:

Siempre al agregar un fragmento,

 fragmentTransaction.add(R.id.fragment_container, detail_fragment, "Fragment_tag").addToBackStack(null).commit(); 

Luego, en la actividad principal, anula onBackPressed()

 if (getSupportFragmentManager().getBackStackEntryCount() > 0) { getSupportFragmentManager().popBackStack(); } else { finish(); } 

Para manejar el botón Atrás en su aplicación,

 Fragment f = getActivity().getSupportFragmentManager().findFragmentByTag("Fragment_tag"); if (f instanceof FragmentName) { if (f != null) getActivity().getSupportFragmentManager().beginTransaction().remove(f).commit() } 

¡Eso es!

Mejor solución,

 import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v7.app.AppCompatActivity; public class BaseActivity extends AppCompatActivity { @Override public void onBackPressed() { FragmentManager fm = getSupportFragmentManager(); for (Fragment frag : fm.getFragments()) { if (frag == null) { super.onBackPressed(); finish(); return; } if (frag.isVisible()) { FragmentManager childFm = frag.getChildFragmentManager(); if (childFm.getFragments() == null) { super.onBackPressed(); finish(); return; } if (childFm.getBackStackEntryCount() > 0) { childFm.popBackStack(); return; } else { fm.popBackStack(); if (fm.getFragments().size() <= 1) { finish(); } return; } } } } } 

En el ciclo de vida de la actividad, siempre el botón de retroceso de Android trata las transacciones de FragmentManager cuando utilizamos FragmentActivity o AppCompatActivity.

Para manejar la backstack no necesitamos manejar su conteo de backstack ni etiquetar nada, pero debemos mantener el foco al agregar o reemplazar un fragmento. Encuentre los siguientes fragmentos para manejar los casos del botón Atrás,

  public void replaceFragment(Fragment fragment) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); if (!(fragment instanceof HomeFragment)) { transaction.addToBackStack(null); } transaction.replace(R.id.activity_menu_fragment_container, fragment).commit(); } 

Aquí, no agregaré stack de nuevo para mi fragmento de inicio porque es la página de inicio de mi aplicación. Si agregas addToBackStack a HomeFragment, la aplicación esperará para eliminar todo el fragmento en actividad, luego obtendremos una pantalla en blanco, así que mantendré la siguiente condición:

 if (!(fragment instanceof HomeFragment)) { transaction.addToBackStack(null); } 

Ahora, puede ver el fragmento agregado anteriormente en acitvity y la aplicación se cerrará cuando llegue a HomeFragment. también puedes mirar los siguientes fragmentos.

 @Override public void onBackPressed() { if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) { closeDrawer(); } else { super.onBackPressed(); } } 

Es simplemente simple si tienes una actividad A y haces 3 fragmentos como B, C y D. Ahora si estás en el fragmento B o C y en la parte onBackPressed quieres moverte en el fragmento D todo el tiempo. Luego tienes que onBackPressed() el onBackPressed() method in main Activity A and also when you jump to any fragment then pass a TAG or name of that fragment by which you recognized that fragment in main Activity A.

I am giving the example of that one by which you can easily understand that….

 if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction().add(R.id.container, new C_fragment(),"xyz").commit(); } 

or if you are moving from fragment B to fragment C..and on back press you want to come on Fragment D…like below

 btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { getActivity().getSupportFragmentManager().beginTransaction().add(R.id.container, new C_frament(), "xyz").commit(); ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle("Fragment C"); } }); 

Now you have to just override the onBackPressed() method in main activity….like below..

 @Override public void onBackPressed() { FragmentManager fragmentManager =getSupportFragmentManager(); if (((C_fragment) getSupportFragmentManager().findFragmentByTag("xyz")) != null && ((C_fragment) getSupportFragmentManager().findFragmentByTag("xyz")).isVisible()) { Fragment fragment = new D_Fragment(); fragmentManager.beginTransaction().replace(R.id.container, fragment).commit(); getSupportActionBar().setTitle("D fragment "); } else { super.onBackPressed(); } } 

I have used another approach as follows:

  • An Otto event bus to communicate between the Activity and its Fragments
  • A Stack in the Activity containing custom back actions wrapped in a Runnable that the calling fragment defines
  • When onBackPressed is called in the controlling Activity, it pops the most recent custom back action and executes its Runnable . If there’s nothing on the Stack, the default super.onBackPressed() is called

The full approach with sample code is included here as an answer to this other SO question .

public class MyActivity extends Activity {

 protected OnBackPressedListener onBackPressedListener; public interface OnBackPressedListener { void doBack(); } public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) { this.onBackPressedListener = onBackPressedListener; } @Override public void onBackPressed() { if (onBackPressedListener != null) onBackPressedListener.doBack(); else super.onBackPressed(); } @Override protected void onDestroy() { onBackPressedListener = null; super.onDestroy(); } 

}

in your fragment add the following, dont forget to implement mainactivity’s interface.

 public class MyFragment extends Framgent implements MyActivity.OnBackPressedListener { @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); ((MyActivity) getActivity()).setOnBackPressedListener(this); } @Override public void doBack() { //BackPressed in activity will call this; } } 

I know it’s too late but I had the same problem last week. None of the answers helped me. I then was playing around with the code and this worked, since I already added the fragments.

In your Activity, set an OnPageChangeListener for the ViewPager so that you will know when the user is in the second activity. If he is in the second activity, make a boolean true as follows:

  mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager()); // Set up the ViewPager with the sections adapter. mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mSectionsPagerAdapter); mViewPager.setCurrentItem(0); mViewPager.addOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { // TODO Auto-generated method stub mSectionsPagerAdapter.instantiateItem(mViewPager, position); if(position == 1) inAnalytics = true; else if(position == 0) inAnalytics = false; } @Override public void onPageScrolled(int position, float arg1, int arg2) { // TODO Auto-generated method stub } @Override public void onPageScrollStateChanged(int arg0) { // TODO Auto-generated method stub } }); 

Now check for the boolean whenever back button is pressed and set the current item to your first Fragment:

 @Override public void onBackPressed() { if(inAnalytics) mViewPager.setCurrentItem(0, true); else super.onBackPressed(); } 
 @Override public void onResume() { super.onResume(); getView().setFocusableInTouchMode(true); getView().requestFocus(); getView().setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { // handle back button replaceFragmentToBackStack(getActivity(), WelcomeFragment.newInstance(bundle), tags); return true; } return false; } }); } 

Ok guys I finally found out a good solution.

In your onCreate() in your activity housing your fragments add a backstack change listener like so:

  fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { List f = fragmentManager.getFragments(); //List f only returns one value Fragment frag = f.get(0); currentFragment = frag.getClass().getSimpleName(); } }); 

(Also adding my fragmenManager is declared in the activities O Now every time you change fragment the current fragment String will become the name of the current fragment. Then in the activities onBackPressed() you can control the actions of your back button as so:

  @Override public void onBackPressed() { switch (currentFragment) { case "FragmentOne": // your code here return; case "FragmentTwo": // your code here return; default: fragmentManager.popBackStack(); // default action for any other fragment (return to previous) } } 

I can confirm that this method works for me.

I had the same problem and I created a new listener for it and used in my fragments.

1 – Your activity should have a listener interface and a list of listeners in it

2 – You should implement methods for adding and removing the listeners

3 – You should override the onBackPressed method to check that any of the listeners use the back press or not

 public class MainActivity ... { /** * Back press listener list. Used for notifying fragments when onBackPressed called */ private Stack backPressListeners = new Stack(); ... /** * Adding new listener to back press listener stack * @param backPressListener */ public void addBackPressListener(BackPressListener backPressListener) { backPressListeners.add(backPressListener); } /** * Removing the listener from back press listener stack * @param backPressListener */ public void removeBackPressListener(BackPressListener backPressListener) { backPressListeners.remove(backPressListener); } // Overriding onBackPressed to check that is there any listener using this back press @Override public void onBackPressed() { // checks if is there any back press listeners use this press for(BackPressListener backPressListener : backPressListeners) { if(backPressListener.onBackPressed()) return; } // if not returns in the loop, calls super onBackPressed super.onBackPressed(); } } 

4 – Your fragment must implement the interface for back press

5 – You need to add the fragment as a listener for back press

6 – You should return true from onBackPressed if the fragment uses this back press

7 – IMPORTANT – You must remove the fragment from the list onDestroy

 public class MyFragment extends Fragment implements MainActivity.BackPressListener { ... @Override public void onAttach(Activity activity) { super.onCreate(savedInstanceState); // adding the fragment to listener list ((MainActivity) activity).addBackPressListener(this); } ... @Override public void onDestroy() { super.onDestroy(); // removing the fragment from the listener list ((MainActivity) getActivity()).removeBackPressListener(this); } ... @Override public boolean onBackPressed() { // you should check that if this fragment is the currently used fragment or not // if this fragment is not used at the moment you should return false if(!isThisFragmentVisibleAtTheMoment) return false; if (isThisFragmentUsingBackPress) { // do what you need to do return true; } return false; } } 

There is a Stack used instead of the ArrayList to be able to start from the latest fragment. There may be a problem also while adding fragments to the back stack. So you need to check that the fragment is visible or not while using back press. Otherwise one of the fragments will use the event and latest fragment will not be closed on back press.

I hope this solves the problem for everyone.

on mainActivity

 protected DrawerHomeActivity.OnBackPressedListener onBackPressedListener; public interface OnBackPressedListener { void doBack(); } public void setOnBackPressedListener(DrawerHomeActivity.OnBackPressedListener onBackPressedListener) { this.onBackPressedListener = onBackPressedListener; } @Override public void onBackPressed() { if (onBackPressedListener != null) { onBackPressedListener.doBack(); } else super.onBackPressed(); } 

on fragment implement base activity/fragment like

 implements DrawerHomeActivity.OnBackPressedListener 

DraweHomeActivity is my base activity write

 ((DrawerHomeActivity) getActivity()).setOnBackPressedListener(this); 

and create method doBack

 @Override public void doBack() { //call base fragment } 

Fragment: Make a BaseFragment placing a method:

  public boolean onBackPressed(); 

Actividad:

 @Override public void onBackPressed() { List fragments = getSupportFragmentManager().getFragments(); if (fragments != null) { for (Fragment fragment : fragments) { if (!fragment.isVisible()) continue; if (fragment instanceof BaseFragment && ((BaseFragment) fragment).onBackPressed()) { return; } } } super.onBackPressed(); } 

Your activity will run over the attached and visible fragments and call onBackPressed() on each one of them and abort if one of them returns ‘true’ (meaning that it has been handled, so no further actions).