How to uncheck checked items in Navigation View?

2019-02-07 18:23发布

问题:

I know it's possible to highlight a navigation view item by calling setCheckedItem() or return true value in onNavigationItemSelected to display the item as the selected item, but How can I uncheck the checked items of a navigation view?

回答1:

This will uncheck the items:

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


回答2:

I saw @arsent solution and gave it a try, and it will indeed do what you want, which is to unselect all the items... but, I was having an issue in the following scenario:

  1. Select menu item 1 (using NavigationView#setCheckedItem)
  2. Unselect all the items as per @arsent's solution
  3. Select menu item 1 again (using NavigationView#setCheckedItem)

In this scenario, item 1 will not be marked as checked. That's because internally the navigation view keeps track of the previously selected item set in step 1, which doesn't change in step 2, and it just skips step 3 because the previously selected item is the same as the one we're selecting now.

My suggestion (and an alternative solution) to avoid this is just having a dummy invisible item and use NavigationView#setCheckedItem to select that item whenever you want to unselect all, like so

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

To unselect all just do

mNavigationView.setCheckedItem(R.id.menu_none);


回答3:

To uncheck all MenuItems including SubMenu items you have to use recursion -

    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);
            }
        }
    }

Call above method for unchecking all items, like below -

unCheckAllMenuItems(navigationView.getMenu());


回答4:

just make your items non checkable like so

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


回答5:

Quoting @Codeversed, there is "no need to loop menu items with added overhead!". But, there is no need to create multiple groups (in this case he is creating the @+id/grp1 and @+id/grp2) to uncheck a previous checked item.

You can simple add a single group for all elements with the android:checkableBehavior, like this:

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



回答6:

Joao's solutions didn't not work for me as totally expected. This would lead to a blank space from unchecked Item View on my Navigation.

Just make sure to set the view as gone:

<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 solution is not necessary in this case.



回答7:

I guess someone like me use those methods just like this

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

Trying to check R.id.nav_today after you clicked on R.id.nav_calendar, (btw: checkableBehavior="single"), unfortunately it will not work.

That is because after your code navigationView.setCheckedItem(R.id.nav_today) be called then the R.id.nav_today will be checked immediately, but after this, your click on R.id.nav_calendar will check itself.

That is why whatever methods you use seem never work at all. It is work, but be override immediately.



回答8:

All you need to do is surround your groups like this:

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

No need to loop menu items with added overhead!



回答9:

i combine @arsent and @Rahul answers and write this code:

 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();

        }

above code is for xamarin c# and work,but u can easily convert to java



回答10:

To uncheck it inside NavigationItemSelectedListener I had to use post (to UI thread):

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

Full example:

 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. in my case App.getHandler() returns Handler instance for UI Thread Lopper