Как установить общее проверяемое поведение для всех групп в NavigationView?
Я создал две группы с уникальными идентификаторами (мне нужен разделитель), и они оба имеют checkableBehavior
Набор single. Это позволяет проверять сразу несколько элементов из разных групп, и именно этого я стараюсь избегать. Я бы хотел, чтобы один пункт был проверен по максимуму, во всех группах.
Поскольку я не нашел способа сделать это в XML, я попытался реализовать простую логику в onNavigationItemSelected
, чтобы снять галочку с предыдущего пункта меню:
if (previousItem != null)
previousItem.setChecked(false);
currentItem.setChecked(true);
Но setChecked(false)
метод никогда не работал для меня - товар остается проверенным.
Вот мой пример кода:
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;
}
});
Мне нужна подсказка! Спасибо.
6 ответов:
Вот решение.
Шаг 1: Удалить
android:checkableBehavior="single"
Из обеих групп.
Шаг 2: Добавьте слушателю следующую логику: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; } });
Примечание: вместо вызова
menuItem.setCheckable(true)
можно задатьandroid:checkable="true"
для каждого элемента в XML.Решение@Moinkhan должно работать так же (спасибо, upvoted), но я не хотел перебирать пункты меню каждый раз, когда выбирается новая позиция.
На самом деле, вам не нужны отдельные параллельные группы для разделителей. Вы можете собрать все в одну группу и поместить в нее подменю (есть названия) или подгруппы (нет названия). Там будут разделители для этих подменю и подгрупп. Таким образом, проверяемое поведение работает без обходного пути. (к вашему сведению: это на Либ поддержки дизайна 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>
В коде я просто делаю следующее, и одиночная проверка работает как ожидается:
@Override public boolean onNavigationItemSelected(MenuItem item) { mNavigationView.setCheckedItem(item.getItemId()); ... }
Не нужно удалять
checkableBehavior="single"
, просто используйтеnavigationView.setCheckedItem(item.getItemId());
Вместо
item.setChecked(true)
.
Хорошо, я нашел решение .. просто добавьте этот фрагмент кода в
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; }
Вот и все .. И да setChecked (false) не работает. Просто потому, что из списка меню должен быть один единственный пункт, который должен быть проверен. Таким образом, вы можете снять его только при выборе другого элемента .. И если вы нажмете на выбранный элемент, navigationview никогда не снимет его флажок. Просто потому, что сценарий я уже объяснил.
В реализации
NavigationView
есть ошибка аннулирования, но вам не нужно использоватьsetCheckable()
, вам просто нужно аннулироватьNavigationView
после вызоваsetChecked(false)
, например:previousItem.setChecked(false); navigationView.invalidate();
Однако группа меню не должна иметь
checkableBehavior="single"
, потому что в исключительном режиме вызовsetChecked(boolean)
наMenuItem
в группе установит этот пункт как проверенный, передаете ли вы true или false. Таким образом, чтобыsetChecked(false)
работал, вы должны удалитьcheckableBehavior="single"
из ваших определений меню.Я создал проблему об этом здесь: https://code.google.com/p/android/issues/detail?id=178709
Вот простое и милое решение, которое я опубликовал здесь:)
Создание различных групп действительно делает разделитель между ними, но создает проблему двух проверенных элементов в навигационном ящике.
Простой способ, как я справился с этим, был:
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);
}