Как установить общее контролируемое поведение во всех группах в NavigationView?
Я создал две группы с уникальными идентификаторами (мне нужен делитель), и оба они имеют checkableBehavior
для одного. Это позволяет сразу проверять сразу несколько элементов из разных групп, и именно этого я и стараюсь избежать. Я бы хотел, чтобы один элемент был отмечен максимум, во всех группах.
Так как я не нашел никакого способа сделать это в 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;
}
});
Мне нужен намек! Спасибо.
Ответы
Ответ 1
Здесь решение.
Шаг 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 должно работать также (спасибо, сохранено), но я не хотел прокручивать пункты меню каждый раз, когда выбрана новая позиция.
Ответ 2
На самом деле вам не нужны отдельные параллельные группы для разделителей. Вы можете иметь все в одной группе и размещать подменю (иметь названия) или подгруппы (без названия). Для этих подменю и подгрупп будут разделители. Таким образом, проверяемое поведение работает без обходного пути.
(Fyi: это поддержка дизайна Lib 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());
...
}
Ответ 3
Не нужно удалять checkableBehavior="single"
, просто используйте
navigationView.setCheckedItem(item.getItemId());
вместо item.setChecked(true)
.
Ответ 4
Хорошо, я нашел решение..
просто добавьте этот код фрагмента в метод 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) не работает. Просто потому, что из списка меню должен быть выбран один отдельный элемент. Таким образом, вы можете снять этот флажок только при выборе другого элемента. И если вы нажмете на выбранный элемент, навигационное представление никогда не отключит его. Просто потому, что сценарий я объяснил.
Ответ 5
В реализации 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
Ответ 6
Здесь простое и сладкое решение, которое я разместил здесь:)
Создание разных групп делает разделитель между ними. Но создает проблему с двумя проверенными элементами в навигационном ящике.
Простым способом, которым я занимался, было следующее:
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);
}
Ответ 7
Нет необходимости в Java-коде, вы можете сделать это с помощью следующего примера XML, где вы сможете выбрать только один элемент в двух группах (основная группа без названия и "Вторая группа"):
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav1"
android:title="Nav 1" />
<item
android:id="@+id/nav2"
android:title="Nav 2" />
<item
android:id="@+id/nav3"
android:title="Nav 3" />
<item
android:id="@+id/nav4"
android:title="Nav 4" />
</group>
<item android:title="Second group">
<menu>
<group android:checkableBehavior="single">
<item
android:id="@+id/nav5"
android:title="Nav 5" />
<item
android:id="@+id/nav6"
android:title="Nav 6" />
</group>
</menu>
</item>
</menu>