Regrese programáticamente al fragmento anterior en el backstack

218

Digamos que tengo una actividad que tiene fragmentos agregados mediante programación:

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

¿Cuál es la mejor manera de volver al fragmento anterior que era visible?

Encontré la funcionalidad del botón de retroceso del disparador al hacer clic en el botón en Android, pero creo que simular un evento de tecla de retroceso no es la forma correcta de hacerlo (y tampoco puedo hacer que funcione):

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

Llamar finish()solo cierra la actividad que no me interesa.

¿Hay una mejor manera de hacerlo?

Aske B.
fuente

Respuestas:

354

Mire los getFragmentManager().popBackStack()métodos (hay varios para elegir)

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

inmaculado
fuente
91
getFragmentManager().popBackStackImmediate();Hizo el truco. Gracias.
Aske B.
1
¿Dónde pondría este método? En mi pestaña oyente?
rasen58
1
sin ver el código, es difícil de decir ... pero debería ir en la sección de código que se ejecuta cuando desea "cerrar" el fragmento actual y volver al fragmento anterior.
atascado
1
¿Qué pasa con getSupportFragmentManager ()
ViliusK
55
No olvide agregar "addToBackStack (" etiqueta ")" en su código. "fragmentManager.beginTransaction (). replace (R.id.content_frame, fragment) .addToBackStack (" tag "). commit ();" si escribe addToBackStack (nulo), lo manejará solo, pero si le da una etiqueta, debe manejarlo manualmente.
Khaled Saif
129

Para elaborar sobre las otras respuestas proporcionadas, esta es mi solución (colocada en una Actividad):

@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();  
    }
}
Kyle Falconer
fuente
55
y por qué está pasando eso? En el ejemplo de fragmento developer.android.com/training/basics/fragments/index.html , no anulan el evento onbackpressed y, sin embargo, pueden apilar el fragmento. He usado trasaction.addToBackStack (nulo); pero nada pasa. Puedes explicar porque ?
Murtaza Khursheed Hussain
@ MurtazaHussain probablemente deberías hacer una nueva pregunta si quieres ayuda con esto. Es un poco difícil ver lo que está sucediendo sin mirar más código.
Kyle Falconer
2
En mi caso, tuve que hacer fm.getBackStackEntryCount() > 1para volver a llamar a la actividad cuando solo hay el primer fragmento en la pila.
Facundo Olano
3
Android ya hace esto por usted: "Cuando hay objetos FragmentTransaction en la pila posterior y el usuario presiona el botón Atrás, el FragmentManager saca la transacción más reciente de la pila posterior y realiza la acción inversa (como eliminar un fragmento si la transacción lo agregó) ". (Fuente)
artkoenig
29

Cuando estamos actualizando / agregando los fragmentos,

Debe incluir el .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();

Después de eso, si le damos, el resultado getFragments.popBackStackImmediate()será verdadero si agregamos / actualizamos los fragmentos y volvemos a la pantalla actual.

Jabeer
fuente
7

Agregue esas líneas a su Método onBackPressed (). El método popBackStackImmediate () lo llevará de regreso al fragmento anterior si tiene algún fragmento en la pila posterior `

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

``

Avijit Biswas
fuente
5

Esta solución funciona perfectamente para la navegación de fragmentos basada en la barra inferior cuando desea cerrar la aplicación cuando se vuelve a presionar en el fragmento primario.

Por otro lado, cuando está abriendo el fragmento secundario (fragmento en fragmento) que se define como "DetailPizza" en mi código, devolverá el estado anterior del fragmento primario. Salud !

Las actividades internas en la parte posterior presionadas ponen esto:

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);
}

Y lanza el otro fragmento así:

Fragment someFragment = new FragmentDetailedPizza();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container_body, someFragment, "DetailedPizza");
transaction.addToBackStack("DetailedPizza");
transaction.commit();
Giedrius Šlikas
fuente
3

Estas respuestas no funcionan si no tengo addToBackStack () agregado a mi transacción de fragmento, pero puede usar:

getActivity().onBackPressed();

de cualquier fragmento para retroceder un paso;

Biplob Das
fuente
1

Regrese programáticamente al fragmento anterior usando el siguiente código.

if ( getFragmentManager().getBackStackEntryCount() > 0) 
{
          getFragmentManager().popBackStack();
          return;
}
super.onBackPressed();
Piyush MandaliYa
fuente
1

Para hacer que ese fragmento vuelva a aparecer, solo agregue ese fragmento al backstack que desea volver a presionar, por ejemplo:

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();
        }
    }
});

En el caso anterior, estoy abriendo LoginFragmentcuando Button buttonse presiona, en este momento el usuario está en SignupFragment. Entonces, si addToBackStack(TAG)se llama, dónde TAG = "SignupFragment", luego, cuando se presiona el botón Atrás LoginFragment, volvemos a SignUpFragment.

¡Feliz codificación!

Saurabh Singh
fuente
Creo que TAG no afecta, incluso puede ser nulo.
CoolMind
1

Al agregar fragment_tran.addToBackStack(null)el último fragmento, puedo volver al último fragmento.

agregando nuevo fragmento :

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();
        }
    });
Baljinder Maan
fuente
1

Vine aquí buscando o la misma idea, y mientras tanto se me ocurrió la propia, que creo que no es tan mala y funciona si con ViewPager.

Entonces, lo que hice fue anular el método onBackPressed en la actividad principal que contiene viewPager y configurarlo para que siempre retroceda menos 1 posición hasta que alcance el primer fragmento, luego cierra la actividad.

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

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

Esto podría tener una desventaja, como si solo retrocediera una vez a la izquierda cada vez, por lo que podría no funcionar muy bien si hay pestañas y cambia de posición con fragmentos omitidos (pasar de 0 a 2 y luego presionar hacia atrás lo pondría 1, en lugar de 0)

Aunque para mi caso, con 2 fragmentos en viewPager sin pestañas, funciona bien.

Grzesiek Eman
fuente
Pregunta similar ya ha sido respondida. stackoverflow.com/questions/10863572/…
AtifSayings
0

Pruebe el siguiente código:

@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();
            }
        }
    }
fuerte
fuente