Search code examples
androidcheckboxpopupmenu

Android PopupMenu checkable item does not check


I have this simple PopupMenu, but when I click on an item, the item doesn't get checked. Why?

In documentation is: Menu items in the Icon Menu (from the options menu) cannot display a checkbox or radio button. Radio button is showing, but only state is not changing...

Java

public void showSortPopup() {
    View menuItemView = findViewById(R.id.action_sort);
    PopupMenu popup = new PopupMenu(this, menuItemView);
    popup.inflate(R.menu.sort);
    popup.getMenu().findItem(R.id.sort_def).setChecked(true);
    popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {

        @Override
        public boolean onMenuItemClick(MenuItem item) {

            switch (item.getItemId()) {
                case R.id.sort_def:
                    sortOrder = CardCursorContract.CardCursor.DEFAULT_SORT;
                    mCardsFragment.setSortOrder(sortOrder);
                    savePref();
                    if (item.isChecked()) item.setChecked(false);
                    else item.setChecked(true);
                    break;
                case R.id.sort_asc:
                    sortOrder = CardCursorContract.CardCursor.ALPHABETICAL_ASC_SORT;
                    mCardsFragment.setSortOrder(sortOrder);
                    savePref();
                    if (item.isChecked()) item.setChecked(false);
                    else item.setChecked(true);
                    break;
                case R.id.sort_desc:
                    sortOrder = CardCursorContract.CardCursor.ALPHABETICAL_DESC_SORT;
                    mCardsFragment.setSortOrder(sortOrder);
                    savePref();
                    if (item.isChecked()) item.setChecked(false);
                    else item.setChecked(true);
                    break;
                default:
                    break;
            }
            return false;
        }
    });
    popup.show();
}

XML-File

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item android:id="@+id/sort_def"
      android:title="@string/action_sort_def"
      android:orderInCategory="1"
      android:showAsAction="always" />

<item android:id="@+id/sort_asc"
      android:title="@string/action_sort_name"
      android:orderInCategory="2"
      android:showAsAction="always" />

<item
      android:id="@+id/sort_desc"
      android:title="@string/action_sort_name_desc"
      android:orderInCategory="3"
      android:showAsAction="always"/>
</group>

Screen

enter image description here


Solution

  • First of all you can simplify the if checked else statement to

    item.setChecked(!item.isChecked())
    

    That way it will always toggle it from true → false and the other way around.

    But the problem lies in the fact that you have radiobuttons, what the statement above does is makes the group checked, but what you want is to have the item checked.

    To get the behaviour youre looking for you can use item.getSubmMenu() and then use the setChecked method on the particular subMenuItem you want.

    For example:

    //This will refer to the default, ascending or descending item.
    MenuItem subMenuItem = item.getSubMenu().getItem(INDEX_OF_ITEM); 
    //Check or uncheck it.
    subMenuItem.setChecked(!subMenuItem.isChecked());