Cómo establecer el comportamiento de comprobación compartida en todos los grupos en NavigationView?
He creado dos grupos con identificadores únicos (necesito un divisor) y ambos tienen checkableBehavior
configurado como single . Esto permite que varios elementos de diferentes grupos se verifiquen a la vez, y eso es exactamente lo que estoy tratando de evitar. Me gustaría tener un elemento marcado al máximo, en todos los grupos.
Como no he encontrado ninguna forma de hacerlo en XML, intenté implementar una lógica simple en onNavigationItemSelected
para desmarcar el elemento de menú anterior:
- Cómo inflar android NavigationView con otro menú dinámicamente durante onClick?
- DrawerLayout con NavigationView - no mostrar el efecto de rizo en el clic
- Cambiar la separación entre el grupo de encabezados y el primer elemento
- La suspensión de soporte de Android v23.1.0 se desplaza
- ¿Agregar MenuItem a NavigationView con el icono y el título?
if (previousItem != null) previousItem.setChecked(false); currentItem.setChecked(true);
Pero el setChecked(false)
nunca ha funcionado para mí – el elemento permanece marcado.
Aquí está mi código de ejemplo:
Menu_navigation.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:id="@+id/nav_group_1" android:checkableBehavior="single"> <item android:id="@+id/nav_feed" android:title="@string/feed"/> <item android:id="@+id/nav_people" android:title="@string/people"/> </group> <group android:id="@+id/nav_group_2" android:checkableBehavior="single"> <item android:id="@+id/nav_settings" android:title="@string/settings"/> <item android:id="@+id/nav_help_feedback" android:title="@string/help_feedback"/> <item android:id="@+id/nav_logout" android:title="@string/logout"/> </group>
NavigationItemSelectedListener:
mUiNavigationView.setNavigationItemSelectedListener( new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(MenuItem menuItem) { if (previousItem != null) previousItem.setChecked(false); currentItem.setChecked(true); //... changeCurrentFragment(...); return true; } });
¡Necesito una pista! Gracias.
- Cómo poner el botón Cerrar sesión de Facebook al final de la vista de navegación
- Cómo cambiar el tamaño del icono de elemento de menú en NavigationView?
- Agregar hijo a un MenuItem dentro de un grupo en un NavigationView
- ¿Cómo puedo eliminar el relleno superior innecesario de la vista de navegación?
- Horarios de reciclaje en DrawerLayout
- DrawerLayout, NavigationView y android: Theme.Material.Light no es compatible?
- NavigationView no está visible pero el clic de artículo está funcionando
- ¿Cómo puedo abrir mediante programación (mostrar en pantalla) NavigationView
Aquí está la solución.
Paso 1: Eliminar
android:checkableBehavior="single"
De ambos grupos.
Paso 2: Agregue la siguiente lógica al oyente:
mUiNavigationView.setNavigationItemSelectedListener( new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(MenuItem menuItem) { menuItem.setCheckable(true); menuItem.setChecked(true); if (mPreviousMenuItem != null) { mPreviousMenuItem.setChecked(false); } mPreviousMenuItem = menuItem; //... changeCurrentFragment(...); return true; } });
Nota: en lugar de llamar a menuItem.setCheckable(true)
puedes establecer android:checkable="true"
para cada elemento en XML.
@ La solución de Moinkhan debe funcionar también (gracias, upvoted), pero no quería hacer bucle a través de los elementos del menú cada vez que se selecciona una nueva posición.
En realidad, no es necesario separar grupos paralelos para separadores. Puedes tener todo en un grupo y colocar submenús (tener títulos) o subgrupos (sin título) en él. Habrá separadores para esos submenús y subgrupos. De esta manera el comportamiento comprobable funciona sin una solución. (Fyi: Esto está en el Libro de Apoyo de Diseño 23.1.1)
<group android:id="@+id/drawer_group" android:checkableBehavior="single"> <item android:id="@+id/nav_1" android:title="Menu1" /> <item android:id="@+id/nav_2" android:title="Menu2" /> <item android:id="@+id/nav_3" android:title="Menu3" /> <item android:id="@+id/nav_4" android:title="Menu4" /> <item android:id="@+id/drawer_submenu" android:title="Subheader"> <menu> <group android:checkableBehavior="single"> <item android:id="@+id/nav_sub1_1" android:title="Menu_Sub1_1" /> <item android:id="@+id/nav_sub1_2" android:title="Menu_Sub1_2" /> </group> </menu> </item> <group android:id="@+id/drawer_subgroup"> <item android:id="@+id/nav_subgroup_item" android:title="Menu_Sub2_2" /> </group> </group>
En código, simplemente hago las siguientes y una sola comprobación funciona como se esperaba:
@Override public boolean onNavigationItemSelected(MenuItem item) { mNavigationView.setCheckedItem(item.getItemId()); ... }
No es necesario eliminar checkableBehavior="single"
, solo usa
navigationView.setCheckedItem(item.getItemId());
En lugar de item.setChecked(true)
.
Ok encontré la solución .. solo agrega este código de fragmento al método onNavigationItemSelected
@Override public boolean onNavigationItemSelected(MenuItem menuItem) { Menu m = navView.getMenu(); for (int i=0;i<m.size();i++) { MenuItem mi = m.getItem(i); if (!(mi.getItemId() == menuItem.getItemId())) { mi.setCheckable(false); } } menuItem.setCheckable(true); menuItem.setChecked(true); return false; }
Eso es todo .. Y sí setChecked (falso) no funciona. Sólo porque de la lista de menú debe haber un solo elemento debe ser cheked. Así que sólo puede desmarcarlo cuando seleccione otro elemento. Y si hace clic en el elemento seleccionado, la vista de navegación nunca lo desmarcará. Sólo porque el escenario que he explicado.
Parece que hay un error de invalidación en la implementación de NavigationView
, pero no es necesario usar setCheckable()
, sólo tiene que invalidar NavigationView
después de llamar a setChecked(false)
, así:
previousItem.setChecked(false); navigationView.invalidate();
Sin embargo, el grupo de menús no debe tener checkableBehavior="single"
, ya que en modo exclusivo llamando setChecked(boolean)
en un MenuItem
del grupo configurará ese elemento como verificado si pasa true o false. Así que para que setChecked(false)
funcione, debes quitar checkableBehavior="single"
de las definiciones de tu menú.
He creado un problema sobre esto aquí: https://code.google.com/p/android/issues/detail?id=178709
Aquí está una solución simple y dulce que posteé aquí 🙂
Hacer grupos diferentes hace un divisor entre los dos pero crea el problema de dos elementos marcados en el cajón de nav.
Una manera simple cómo manejé esto era:
public boolean onNavigationItemSelected(final MenuItem menuItem) { //if an item from extras group is clicked,refresh NAV_ITEMS_MAIN to remove previously checked item if (menuItem.getGroupId() == NAV_ITEMS_EXTRA) { navigationView.getMenu().setGroupCheckable(NAV_ITEMS_MAIN, false, true); navigationView.getMenu().setGroupCheckable(NAV_ITEMS_EXTRA, true, true); }else{ navigationView.getMenu().setGroupCheckable(NAV_ITEMS_MAIN, true, true); navigationView.getMenu().setGroupCheckable(NAV_ITEMS_EXTRA, false, true); } //Update highlighted item in the navigation menu menuItem.setChecked(true);
}
- Obtener Android versión del sistema operativo del dispositivo conectado a través de adb
- DialogFragment y botón Atrás