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

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

10 ответов

Решение

Это снимет галочки с пунктов:

    int size = mNavigationView.getMenu().size();
    for (int i = 0; i < size; i++) {
        mNavigationView.getMenu().getItem(i).setChecked(false);
    }

Я увидел решение @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);

Снять все 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());

Просто сделайте свои вещи не проверяемыми, как это так

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

Цитируя @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>

Решения Хуана не сработали для меня, как ожидалось. Это привело бы к пустому пространству от непроверенного Представления Пункта на моей Навигации.

Просто убедитесь, что установили представление как пропавшее:

<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 не требуется.

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

 <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>

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

Снять галочку внутри 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;
                });

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

Я думаю, кто-то, как я, использует эти методы так же, как это

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 проверим себя.

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

Мне пришлось использовать комбинацию всех упомянутых здесь решений. В моем случае я хочу открыть намерение 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.

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

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

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

    for (int i = 0; i < size; i++) {
        mNavigationView.getMenu().getItem(i).setChecked(false);
    }

Я комбинирую ответы @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

Другие вопросы по тегам