Как снять отметку с отмеченных пунктов в представлении навигации?

Я знаю, что можно выделить элемент представления навигации, вызвав setCheckedItem(), или вернуть истинное значение в onNavigationItemSelected, чтобы отобразить элемент как выбранный, но как снять отметку с отмеченных элементов в представлении навигации?


person Hafez Divandari    schedule 17.03.2016    source источник


Ответы (12)


Это снимет отметку с пунктов:

int size = mNavigationView.getMenu().size();
for (int i = 0; i < size; i++) {
    mNavigationView.getMenu().getItem(i).setChecked(false);
}
person arsent    schedule 17.03.2016
comment
Я не знаю, после использования вашего кода у меня остается пустое место! - person phpdroid; 14.09.2017
comment
в моем случае, после использования вашей техники, я проверил последний пункт и не могу его решить. пожалуйста, помогите мне... - person takmilul; 26.12.2017
comment
@takmilul убедитесь, что вы используете setChecked(false);, а не true - person arsent; 26.12.2017
comment
с предложенным кодом будет выбран последний элемент. Решил проблему заменой setChecked(false) на setCheckable(false) - person Roberto; 28.12.2017
comment
setCheckable(false) в сочетании с setChecked(false) для каждого элемента, сработавшего в моем случае. - person kkaun; 01.09.2018
comment
Несмотря на то, что он снимает отметки со всех элементов, он предотвращает их проверку в будущем. - person Thorsten Dittmar; 19.09.2019
comment
использовать setChecked (false) - person Yogesh Nikam Patil; 14.01.2020

Я увидел решение @arsent и попробовал, и оно действительно сделает то, что вы хотите, а именно отменит выбор всех элементов ... но у меня возникла проблема в следующем сценарии:

  1. Выберите пункт меню 1 (используя NavigationView#setCheckedItem)
  2. Отмените выбор всех элементов в соответствии с решением @arsent
  3. Снова выберите пункт меню 1 (используя NavigationView#setCheckedItem)

В этом случае элемент 1 не будет отмечен как отмеченный. Это потому, что внутреннее представление навигации отслеживает ранее выбранный элемент, установленный на шаге 1, который не изменяется на шаге 2, и он просто пропускает шаг 3, потому что ранее выбранный элемент совпадает с тем, который мы выбираем сейчас.

Мое предложение (и альтернативное решение), чтобы избежать этого, - это просто фиктивный невидимый элемент и использование NavigationView#setCheckedItem для выбора этого элемента всякий раз, когда вы хотите отменить выбор всех, например

<item
    android:id="@+id/menu_none"
    android:title=""
    android:visible="false"/>

Чтобы отменить выбор, просто сделайте

mNavigationView.setCheckedItem(R.id.menu_none);
person Joao Sousa    schedule 18.08.2016
comment
Я обнаружил, что мне также нужно сделать этот пункт меню checkable="true", чтобы он работал, но как только я это сделал, он стал идеальным! - person AtkinsSJ; 09.08.2018
comment
это даже быстрее. умное решение! - person M.kazem Akhgary; 02.11.2018
comment
Жаль, что подобная функция не встроена в SDK, и мы должны ее взломать - person Bartek Pacia; 09.03.2019
comment
Какой умный взлом! - person waseefakhtar; 18.10.2019

Чтобы снять отметку со всех MenuItems, включая SubMenu элементы, вы должны использовать рекурсию -

    private void unCheckAllMenuItems(@NonNull final Menu menu) {
        int size = menu.size();
        for (int i = 0; i < size; i++) {
            final MenuItem item = menu.getItem(i);
            if(item.hasSubMenu()) {
                // Un check sub menu items
                unCheckAllMenuItems(item.getSubMenu());
            } else {
                item.setChecked(false);
            }
        }
    }

Вызовите метод выше, чтобы снять отметку со всех элементов, как показано ниже -

unCheckAllMenuItems(navigationView.getMenu());
person Rahul    schedule 01.04.2017

просто сделайте так, чтобы ваши предметы не проверялись

<item
    android:id="@+id/profile_item"
    android:checkable="false"
    android:title="@string/profile"/>
person Jack    schedule 07.05.2018

Цитируя @Codeversed, «нет необходимости зацикливать пункты меню с дополнительными накладными расходами!». Но нет необходимости создавать несколько групп (в этом случае он создает @+id/grp1 и @+id/grp2), чтобы снять отметку с предыдущего отмеченного элемента.

Вы можете просто добавить одну группу для всех элементов с помощью android:checkableBehavior, например:

<group android:checkableBehavior="single">
    <item
        android:id="@+id/id1"
        android:checked="true"
        android:icon="@drawable/drawable1"
        android:title="@string/string1" />

    <item
        android:id="@+id/id2"
        android:icon="@drawable/drawable2"
        android:title="@string/string2" />
</group>

person Filipe Brito    schedule 24.01.2018

Решения Жоао не сработали для меня, как ожидалось. Это приведет к появлению пустого места в непроверенном представлении элементов в моей навигации.

Просто не забудьте установить вид как пропавший:

<item
    android:id="@+id/your_menu_item_id_to_hide"
    android:title=""
    android:visible="false"/>


bottomNavigationView.getMenu().findItem(R.id.your_menu_item_id_to_hide).setChecked(true);
    bottomNavigationView.findViewById(R.id.your_menu_item_id_to_hide).setVisibility(View.GONE);

Раствор Arsent в этом случае не нужен.

person Victor R. Oliveira    schedule 28.12.2016
comment
У меня была такая же проблема, и я ее исправил, но сейчас не могу вспомнить, как. Дважды проверьте параметры xml в файлах макета - person Victor R. Oliveira; 10.02.2017
comment
ах, это нижний вид навигации, который появился недавно. Я никогда не пробовал свое решение с этим компонентом, но приятно знать, что вам удалось его настроить. - person Joao Sousa; 29.03.2017

Все, что вам нужно сделать, это окружить свои группы вот так:

 <group>
    <group
        android:id="@+id/grp1">
        <item
            android:id="@+id/nav_profile"
            android:icon="@drawable/ic_account_circle_24dp"
            android:title="@string/profile" />
    </group>
    <group
        android:id="@+id/grp2">
        <item
            android:id="@+id/nav_settings"
            android:icon="@drawable/ic_settings_24dp"
            android:title="@string/settings" />
        <item
            android:id="@+id/nav_help"
            android:icon="@drawable/topic_help"
            android:title="@string/help_feedback" />
    </group>
</group>

Нет необходимости зацикливать пункты меню с дополнительными накладными расходами!

person Codeversed    schedule 07.08.2017

Думаю, кто-то вроде меня использует эти методы вот так

public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    switch (item.getItemId()) {
        case R.id.nav_today:
            break;
        case R.id.nav_calendar:
           navigationView.getMenu().performIdentifierAction(R.id.nav_today, 0);
           navigationView.getMenu().getItem(0).setChecked(true);//or
           navigationView.setCheckedItem(R.id.nav_today);//or
           drawerLayout.closeDrawers();
           break;
    }
    return true;
}

Попытка проверить R.id.nav_today после того, как вы нажали R.id.nav_calendar, (кстати: checkableBehavior="single"), к сожалению, не сработает.

Это потому, что после того, как ваш код navigationView.setCheckedItem(R.id.nav_today) будет вызван, R.id.nav_today будет немедленно проверен, но после этого ваш щелчок по R.id.nav_calendar проверит себя.

Вот почему какие бы методы вы ни использовали, кажется, что они вообще никогда не работают. Это работа, но ее нужно немедленно отменить.

person KDLin    schedule 12.01.2018

Чтобы снять отметку внутри NavigationItemSelectedListener, мне пришлось использовать сообщение (в поток пользовательского интерфейса):

App.getHandler().post(() -> menuItem.setChecked(false));

Полный пример:

 NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(
                menuItem -> {
                    menuItem.setChecked(true);

                    mDrawerLayout.closeDrawers();

                    switch (menuItem.getItemId()) {
                        ...
                    }

                    App.getHandler().post(() -> menuItem.setChecked(false));

                    return true;
                });

p.s. в моем случае App.getHandler() возвращает Handler экземпляр для UI Thread Lopper

person user924    schedule 31.10.2018

Мне пришлось использовать комбинацию всех упомянутых здесь решений. В моем случае я хочу открыть намерение URL-адреса при щелчке по элементу (открыть браузер). Выбранный элемент должен быть снят после щелчка и сброшен к элементу ранее. Важно понимать, что вы не можете снять отметку с элемента во время события прослушивателя кликов, так как отмеченное состояние будет обработано впоследствии. Итак, это мое решение в Котлине:

        val item = navigationView.menu.findItem(R.id.menu_item)
        item.setOnMenuItemClickListener {

            val oldItem = navigationView.checkedItem
            rootView.postDelayed({ // you can use here any View to post a Runnable with a delay
                navigationView.setCheckedItem(oldItem?.itemId ?: R.id.default_item)
            }, 500)
            browseURL("https://www.example.com")
            true
        }

Я использую панель навигации в сочетании с Jetpack Navigation.

person Paul Spiesberger    schedule 15.05.2019
comment
Большое спасибо, дружище, ты экономишь мое время. - person Muhammad Farhan; 11.06.2020

Я комбинирую ответы @arsent и @Rahul и пишу этот код:

 private void NavigationView_NavigationItemSelected(object sender, NavigationView.NavigationItemSelectedEventArgs e)
        {
            var size = navigationView.Menu.Size();
            for (int i = 0; i < size; i++)
            {
               var item= navigationView.Menu.GetItem(i).SetChecked(false);
                if (item.HasSubMenu)
                {
                    for (int j = 0; j < item.SubMenu.Size(); j++)
                    {
                        item.SubMenu.GetItem(j).SetChecked(false);
                    }
                }
            }
                e.MenuItem.SetChecked(true);

            drawerLayout.CloseDrawers();

        }

приведенный выше код предназначен для xamarin C # и работает, но вы можете легко преобразовать в java

person arman    schedule 08.06.2018

@arsent ответ правильный, но setCheckable (false) снимает отметку со всех элементов, это предотвращает проверку элементов в будущем.

Просто используйте setChecked (false)

  int size = mNavigationView.getMenu().size();

    for (int i = 0; i < size; i++) {
        mNavigationView.getMenu().getItem(i).setChecked(false);
    }
person Yogesh Nikam Patil    schedule 14.01.2020