Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android action bar checkable menu item does not work/show properly?

so I am trying to get my menu item, that is show on the action bar to behave like a checkable menu option. The firs part works, meaning it is checkable and when I press it, and set in code the setChecked(true) it works. But what does not work is the visual part. There is no change in how a menu item looks on the action bar in checked and unchecked states? I tried using invalidateOptionsMenu() but that does not do the job, and not only that, with that line in my code I can't get out of the checked state?!? What happens is that invalidate OptionsMenu() seams to unset the checked state and I end up 'looping', or on every press of that menu item I keep going to the unchecked part of the code where it gets checked and with invalidate it gets unchecked I guess...

Here is the code from my XML file for menu:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/lenslist_menu_add"
        android:showAsAction="always"
        android:title="@string/add"/>
    <item android:id="@+id/lenslist_menu_delete"
        android:showAsAction="always"
        android:checkable="true"
        android:title="@string/delete"/>
</menu>

And here is the java code:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // TODO Auto-generated method stub
    switch (item.getItemId()) {
    case R.id.lenslist_menu_add:

        return true;
    case R.id.lenslist_menu_delete:
        if (item.isChecked() == true) {
            item.setChecked(false);
            deleteMode = false;
            lensAdapter.setDeleteMode(false);
        } else {
            item.setChecked(true);
            deleteMode = true;
            lensAdapter.setDeleteMode(true);
        }
        lensAdapter.notifyDataSetChanged();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Thanks!

like image 630
Dusko Avatar asked Nov 16 '11 08:11

Dusko


People also ask

Which menu affects the selected content while doing action on it?

Context menu and contextual action mode A context menu is a floating menu that appears when the user performs a long-click on an element. It provides actions that affect the selected content or context frame.

What is contextual action bar?

The contextual action mode is a system implementation of ActionMode that focuses user interaction toward performing contextual actions. When a user enables this mode by selecting an item, a contextual action bar appears at the top of the screen to present actions the user can perform on the currently selected item(s).

What is onCreateOptionsMenu in android?

The intent of implementing this method is to populate the menu passed with the items you define in the R. menu. game_menu layout file. #Java @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().


3 Answers

Checkable items appear only in submenus or context menus.

You are using them as main menu items, hence it will not work.

SOURCE: Download the API DEMOS, and open the file ApiDemos/res/menu/checkable.xml, you'll see it as a comment on line 13. I don't know why they don't mention this in the Developer Documentation

reference with comment.: http://alvinalexander.com/java/jwarehouse/android-examples/platforms/android-2/samples/ApiDemos/res/menu/checkable.xml.shtml

like image 94
Entreco Avatar answered Sep 20 '22 05:09

Entreco


Or just do it yourself

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.item1).setIcon(menu_checked?R.drawable.menu_ico_checked:R.drawable.menu_ico_unchecked);
    return super.onPrepareOptionsMenu(menu);
}

and in onOptionsItemSelected do:

 ....
 menu_checked=!menu_checked;
 invalidateOptionsMenu();
like image 40
djdance Avatar answered Sep 21 '22 05:09

djdance


The best solution is to set the actionLayout of the <Item> to a CheckBox. This solution gives you a native-looking checkbox (with material animations etc), with a font that matches the other items, and it works both as an action and in the submenu.

  1. Create a new layout called action_checkbox.html:
<?xml version="1.0" encoding="utf-8"?>
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:paddingStart="8dp"
          android:paddingEnd="8dp"
          android:checked="false"
          android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Menu"
          android:id="@+id/action_item_checkbox"
    />
  1. Set your <Item> like this. Note that you need the Checkable and Checked still in case it is shown in a sub-menu (in which case the actionLayout is ignored.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
    <item android:id="@+id/menu_action_logging"
          android:title="@string/action_logging"
          android:orderInCategory="100"
          android:showAsAction="always"
          android:checkable="true"
          android:checked="false"
          android:actionLayout="@layout/action_checkbox"
        />
</menu>
  1. In your code, when the menu is created we need to a) set the title of the checkbox to match the menu item title, b) restore the checked state of both the menu checkable, and our extra checkbox, and c) add an onClicked() listener for our extra checkbox. In this code I am persisting the state of the checkbox in a RetainedFragment.
    // Set the check state of an actionbar item that has its actionLayout set to a layout
    // containing a checkbox with the ID action_item_checkbox.
    private void setActionBarCheckboxChecked(MenuItem it, boolean checked)
    {
        if (it == null)
            return;

        it.setChecked(checked);

        // Since it is shown as an action, and not in the sub-menu we have to manually set the icon too.
        CheckBox cb = (CheckBox)it.getActionView().findViewById(R.id.action_item_checkbox);
        if (cb != null)
            cb.setChecked(checked);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
    {
        inflater.inflate(R.menu.menu_main, menu);
        super.onCreateOptionsMenu(menu, inflater);

        // Restore the check state e.g. if the device has been rotated.
        final MenuItem logItem = menu.findItem(R.id.menu_action_logging);
        setActionBarCheckboxChecked(logItem, mRetainedFragment.getLoggingEnabled());

        CheckBox cb = (CheckBox)logItem.getActionView().findViewById(R.id.action_item_checkbox);
        if (cb != null)
        {
            // Set the text to match the item.
            cb.setText(logItem.getTitle());
            // Add the onClickListener because the CheckBox doesn't automatically trigger onOptionsItemSelected.
            cb.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onOptionsItemSelected(logItem);
                }
            });
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_action_logging:
                // Toggle the checkbox.
                setActionBarCheckboxChecked(item, !item.isChecked());

                // Do whatever you want to do when the checkbox is changed.
                mRetainedFragment.setLoggingEnabled(item.isChecked());
                return true;
            default:
                break;
        }

        return false;
    }
like image 25
Timmmm Avatar answered Sep 22 '22 05:09

Timmmm