Search code examples
androidsubmenunavigationview

Can't change icons for subitems in NavigationView


I'm trying to do checkbox behaviour in a NavigationView

With no subitems (all top level menu items) I can happily change the icons using the following code:

    mNavigationView.setNavigationItemSelectedListener(
            new NavigationView.OnNavigationItemSelectedListener() {
                @Override
                public boolean onNavigationItemSelected(MenuItem menuItem) {
                    Boolean boolObj = mMenuToggleMap.get(menuItem.getItemId());
                    boolean state = boolObj == null ? true : boolObj.booleanValue();
                    state = !state;
                    if(state) menuItem.setIcon(R.drawable.btn_check_off_holo_light);
                    else      menuItem.setIcon(R.drawable.btn_check_on_holo_light);
                    mMenuToggleMap.put(menuItem.getItemId(), state);
                    return true;
                }
            });

menu.xml:

        <item
            android:id="@+id/books"
            android:title="@string/books"
            android:icon="@drawable/btn_check_off_holo_light"
            app:showAsAction="always"/>

        <item
            android:id="@+id/cddvds"
            android:icon="@drawable/btn_check_off_holo_light"
            android:title="@string/cddvds"
            app:showAsAction="always"/>

As you can see:

enter image description here

However, as soon as I change my XML like so:

<item
    android:id="@+id/categorySubHeader"
    android:title="@string/categories">
    <menu>
        <item
            android:id="@+id/books"
            android:title="@string/books"
            android:icon="@drawable/btn_check_off_holo_light"
            app:showAsAction="always"/>

        <item
            android:id="@+id/cddvds"
            android:icon="@drawable/btn_check_off_holo_light"
            android:title="@string/cddvds"
            app:showAsAction="always"/>

I find that the icons no longer change (even though the code in the listener is still being called). Can anyone give me a clue as to why these items aren't updating?

I'm wondering if an invalidateMenuOptions() can be called on the NavigationView or a notifyDataSetChanged() functionality can be called on the backing data?


Solution

  • First of all make sure that your both item should not be subitem. Because I also face same issue that changing the icon of subitem is not working properly.

    So your XML should look like.

    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        tools:context="ng.edu.binghamuni.bhu.ui.activity.HomeActivity">
    
         <item
                android:id="@+id/books"
                android:title="@string/books"
                android:icon="@drawable/btn_check_off_holo_light"
                app:showAsAction="always"/>
    
            <item
                android:id="@+id/cddvds"
                android:icon="@drawable/btn_check_off_holo_light"
                android:title="@string/cddvds"
                app:showAsAction="always"/>
    
    </menu>
    

    On your Navigation click do the following code.

    navView.setNavigationItemSelectedListener(
        new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
                switch (menuItem.getItemId()) {
                    case R.id.books:
                        menuItem.setIcon((isBookChecked)?R.drawable.btn_check_off_holo_light:R.drawable.btn_check_on_holo_light);
                        isBookChecked = !isBookChecked;
                        break;
                    case R.id.cddvds:
                        menuItem.setIcon((isCdDVDChecked)?R.drawable.btn_check_off_holo_light:R.drawable.btn_check_on_holo_light);
                        isCdDVDChecked = !isCdDVDChecked;
                        break;
                }
                return true;
            }
        });
    

    Just create two variable isBookChecked and isCdDVDChecked globally to maintain checked state manully.

    [Update-------------------/////]

    I spent some time for changing icon of subitem. finally i did it. But currently it's tricky solution. Becuase month ago i have report a bug: https://code.google.com/p/android/issues/detail?id=176300, that we can't add dynamic menu to navigation view. and i think this is also chain of that bug (Update UI issue) .

    So,for solution do following on your navigation click..

    navView.setNavigationItemSelectedListener(
        new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem) {
    
                // change the icon as you need
                menuItem.setIcon(getResources().getDrawable(android.R.drawable.checkbox_on_background));
    
                // here is the trick. Resetting the title of top level item.
                navView.getMenu().getItem(0).setTitle(navView.getMenu().getItem(0).getTitle());
                return true;
            }
        });
    

    Actully when we are changing the icon using setIcon() method. the icon is changing but the issue is that it will not updating UI. So resetting the title of top level item will update UI. I hope it helpful to you.