studio from fragments communicating change activity android android-fragments back-stack android-navigation

from - Android: volver al fragmento anterior en la prensa trasera



communicating fragment (5)

He implementado Navigation Drawer, que es una subclase de Activity. Tengo muchos fragmentos en mi solicitud. Mi pregunta va aqui

Imagina que hay 3 fragmentos:

Fragment_1: Fragmento_2: Fragmento_3

Cuando inicio mi aplicación, Fragment_1 se carga Cuando hago clic en algunos componentes en Fragment_1, me navego a Fragment_2 y así sucesivamente ..

Entonces es como

Fragment_1> Fragmento_2> Fragmento_3

Cuando presiono la tecla Atrás desde Fragment_2, me navego de nuevo a Fragment_1 Pero cuando presiono la tecla Atrás desde Fragment_3, me navego de nuevo a Fragment_1 (en lugar de Fragment_2)

Quiero algo como esto en mi aplicación al presionar la tecla Atrás

Fragment_1 <Fragmento_2 <Fragmento_3

He utilizado Fragment, FragmentManager, FragmentTransaction de la siguiente manera:

MyFragment fragment = new MyFragment(); FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).addToBackStack(null)commit();

e intenté sobrescribir onBackPressed () en mi MainActivity:

@Override public void onBackPressed() { getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); int count = getFragmentManager().getBackStackEntryCount(); if (count == 0) super.onBackPressed(); }


Actualice su método Activity#onBackPressed() para:

@Override public void onBackPressed() { if (getFragmentManager().getBackStackEntryCount() > 0) { getFragmentManager().popBackStack(); } else { super.onBackPressed(); } }

La razón por la que su implementación no funciona es porque el método FragmentManager#popBackStack() es asíncrono y no sucede justo después de que se llama.

De la documentación:

Esta función es asíncrona: encola la solicitud para que aparezca, pero la acción no se realizará hasta que la aplicación vuelva a su bucle de eventos.

Referencia: http://developer.android.com/reference/android/app/FragmentManager.html#popBackStack(java.lang.String,%20int)


Aquí está el código de trabajo y probado por mí, Esto te ayudará

private static final int TIME_INTERVAL = 2000; private long mBackPressed; private void applyExit() { if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) { finish(); } else { Toast.makeText(this,"Press Again to exit",Toast.LENGTH_LONG).show(); } mBackPressed = System.currentTimeMillis(); } @Override public void onBackPressed() { fm = getSupportFragmentManager(); if (drawer.isDrawerOpen(GravityCompat.START)) { drawer.closeDrawer(GravityCompat.START); } if (fm.getFragments().size() <= 1) { applyExit(); } else { for (Fragment frag : fm.getFragments()) { if (frag == null) { applyExit(); return; } if (frag.isVisible()) { FragmentManager childFm = frag.getChildFragmentManager(); if (childFm.getFragments() == null) { super.onBackPressed(); return; } if (childFm.getBackStackEntryCount() > 0) { childFm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); return; } else { fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); return; } } } } }


El tric está en FragmentManager#executePendingTransactions(); .

Esto es lo que uso para los fragmentos anidados también ...

/** * if there is a fragment and the back stack of this fragment is not empty, * then emulate ''onBackPressed'' behaviour, because in default, it is not working. * * @param fm the fragment manager to which we will try to dispatch the back pressed event. * @return {@code true} if the onBackPressed event was consumed by a child fragment, otherwise */ public static boolean dispatchOnBackPressedToFragments(FragmentManager fm) { List<Fragment> fragments = fm.getFragments(); boolean result; if (fragments != null && !fragments.isEmpty()) { for (Fragment frag : fragments) { if (frag != null && frag.isAdded() && frag.getChildFragmentManager() != null) { // go to the next level of child fragments. result = dispatchOnBackPressedToFragments(frag.getChildFragmentManager()); if (result) return true; } } } // if the back stack is not empty then we pop the last transaction. if (fm.getBackStackEntryCount() > 0) { fm.popBackStack(); fm.executePendingTransactions(); return true; } return false; }

y en mi onBackPressed :

if (!FragmentUtils.dispatchOnBackPressedToFragments(fm)) { // if no child fragment consumed the onBackPressed event, // we execute the default behaviour. super.onBackPressed(); }


Tienes que implementar tu propia implementación de backstack como se explica aquí

Separar la pila posterior para cada pestaña en Android usando fragmentos

Puede llamar a popFragments () siempre que haga clic en el botón Atrás en un fragmento y llame a pushFragments () cuando navegue de un Fragmento a otro.

en breve,

public void onBackPressed() { FragmentManager fm = getActivity().getSupportFragmentManager(); fm.popBackStack(); }


Use este código en el cambio de pestaña en su actividad principal para borrar la pila.

int count = getFragmentManager().getBackStackEntryCount(); if(count>0){ for (int i = 0; i <count; i++) { getFragmentManager().popBackStack(); } }

Luego presiona Atrás de tu actividad principal haz esto

int count = getFragmentManager().getBackStackEntryCount(); if (count == 0) { super.onbackpressed(); } else { getFragmentManager().popBackStack(); } }