Actualizar el estado seleccionado del cajón de navegación después de volver a pulsar

¿Cuál es la manera correcta de manejar el estado seleccionado del cajón de navegación después de volver a pulsar?

Tengo un cajón de navegación con n entradas (en un listview) como el SDK muestra en Android Studio. Cuando hago clic en las entradas del cajón de navegación quiero que se agreguen a la pila de atrás, para que pueda volver a ellos.

En onNavigationDrawerItemSelected (int pos) tengo

FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); if (position == 0) { transaction.replace(R.id.container, new FragmentA()); } else if (position == 1) { transaction.replace(R.id.container, new FragmentB()); } else { transaction.replace(R.id.container, new FragmentC()); } transaction.addToBackStack(null); transaction.commit(); 

Cuando hago clic en la segunda entrada en el cajón, B se selecciona y reemplaza A. Si hago clic en el botón Atrás después, el fragmento A se muestra de nuevo como debería, pero B todavía está seleccionado en el cajón de navegación.

¿Cómo puedo obtener el estado de selección del cajón actualizado después de presionar de nuevo?

De alguna manera necesito una llamada a mDrawerListView.setItemChecked (position, true); O NavigationDrawerFragment.selectItem (posición int). Pero, ¿a qué posición? ¿Cómo lo recuerdo?

Interceptar con onBackPressed?

 @Override public void onBackPressed() {} 

Pero, ¿cómo puedo saber qué fragmento está activo de nuevo? Y a qué posición corresponde.

¿Hay alguna solución fácil que soy ciego para ver? Parece que el uso de regreso en combinación con el cajón de navegación y la actualización del estado de selección es un patrón estándar.

4 Solutions collect form web for “Actualizar el estado seleccionado del cajón de navegación después de volver a pulsar”

Este patrón se describe en la sección Implementar la navegación posterior para fragmentos de la documentación "Volver a la navegación adecuada".

Si su aplicación actualiza otros elementos de la interfaz de usuario para reflejar el estado actual de sus fragmentos, como la barra de acciones, recuerde actualizar la interfaz de usuario al confirmar la transacción. Debe actualizar su interfaz de usuario después de que cambie la pila trasera además de cuando confirma la transacción. Puede escuchar cuando una FragmentTransaction se invierte configurando un FragmentManager.OnBackStackChangedListener :

 getSupportFragmentManager().addOnBackStackChangedListener( new FragmentManager.OnBackStackChangedListener() { public void onBackStackChanged() { // Update your UI here. } }); 

Ese sería el lugar adecuado para actualizar la opción actual en el cajón de navegación.

He tenido un montón de problemas para tratar de encontrar una solución a este problema y la solución que acabé utilizando no es "agradable" en mi opinión, pero funciona.

En mi aplicación terminé agregando una posición de fragmentos en el cajón de navegación, cuando agregué el fragmento al backstack. De esta manera podría llamar a setItemChecked con la posición en mi onBackStackChanged (). Así que básicamente lo que hice fue esto:

 @Override public void onBackStackChanged() { FragmentManager fm = getFragmentManager(); String name = fm.getBackStackEntryAt(fm.getBackStackEntryCount()-1).getName(); mDrawerList.setItemChecked(Integer.parseInt(name),true); } public class DrawerItemClickListener implements android.widget.AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { selectItem(position); } } private void selectItem(int position) { Fragment fragment; switch (position) { case 0: // Home fragment = new ContentFragment(); break; case 1: // Another fragment = new AnotherFragment(); break; default: // Logout { finish(); Intent intent = new Intent(this, StartupActivity.class); startActivity(intent); return; } } FragmentManager fragmentManager = getFragmentManager(); fragmentManager.beginTransaction() .replace(R.id.content_frame, fragment) .addToBackStack(Integer.toString(position)) .commit(); mDrawerList.setItemChecked(position, true); setTitle(mNavigationItems[position]); mDrawerLayout.closeDrawer(mDrawerList); } 

Basándose en la respuesta excelente de @matiash (asegúrate de hacer +1 con ella si haces +1 en mi respuesta)

Para comenzar, estamos asumiendo que estamos en la Activity

 getFragmentManager().addOnBackStackChangedListener( new FragmentManager.OnBackStackChangedListener() { public void onBackStackChanged() { // Update your UI here. } }); 

Puede encontrar el fragmento actual con lo siguiente:

(Desde https://stackoverflow.com/a/24589081/878159 )

 Fragment f = getFragmentManager().findFragmentById(R.id.frag_container); if (f instanceof CustomFragmentClass) { // do something with f f.doSomething(); } 

Eso debería acercarte un paso más. Entonces algo como esto le conseguirá una referencia a su cajón del nav:

 nav = (NavigationDrawerFragment) getFragmentManager().findFragmentById(R.id.nav); 

A continuación, dependiendo de cómo configurar el código de fragmento de cajón:

 nav.updateSelected(position); 

El updateSelected(int) estaría en su clase NavigationDrawerFragment y podría parecer algo así:

 public void updateSelected(int position) { mCurrentSelectedPosition = position; if (mDrawerListView != null) { mDrawerListView.setItemChecked(position, true); } } 

NOTA: hay muchas maneras de hacer esto, pero esto debería empezar.

Hoy tuve la misma resistencia. Lo resolví mediante la implementación de una interfaz FragmentToActivity en cada fragmento y en mi uno y sólo MainActivity.

Interfaz:

 public interface FragmentToActivity { public void SetNavState(int id); } 

Fragmentos:

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ((FragmentToActivity) getActivity()).SetNavState(R.id.nav_myitemid); //just add this line } 

Actividad principal:

 @Override public void SetNavState(int id) { NavigationView nav = (NavigationView) findViewById(R.id.nav_view); nav.setCheckedItem(id); } 

Y si no tienes idea de dónde viene R.id.nav_myitemid , aquí está mi activity_main_drawer.xml :

 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/nav_myitemid" android:title="@string/home" /> </group> </menu> 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.