Подтвердить что ты не робот

Как установить общее контролируемое поведение во всех группах в 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;
                    }
                });

Мне нужен намек! Спасибо.

4b9b3361

Ответ 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>