1

I have some items in an ActionBar sub menu which I would like to conditionally disable, because they are not applicable for some contexts. I would like them to appear disabled (greyed out) to discourage users from clicking them; but if clicked, I would like to show a toast informing the user of why it is disabled ("can't do A because there is no B", etc). However, if I call MenuItem.setEnabled(false), it seems all the menu item click events do not occur. So, how do I detect click on the disabled menu item?

public class Temp extends Activity implements OnMenuItemClickListener
{
    boolean mConditional = true;

    protected void onCreate(Bundle state)
    {
        super.onCreate(state);
    }

    public boolean onMenuOpened(int featureId, Menu menu)
    {
        MenuItem item = (MenuItem) menu.findItem(R.id.item2);
        if(item != null && mConditional)
        {
            item.setEnabled(false);
            item.setOnMenuItemClickListener(this);
        }

        return super.onMenuOpened(featureId, menu);
    }

    @Override
    public boolean onMenuItemClick(MenuItem item) 
    {
        //does not fire if item is disabled
        Log.e("", item.getTitle().toString());
        return true;
    }



    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        //does not fire if item is disabled
        Log.e("", item.getTitle().toString());
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item)
    {
        //does not fire if item is disabled
        Log.e("", item.getTitle().toString());
        return super.onMenuItemSelected(featureId, item);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main, menu);
        return true;
    }
}

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menu"
        android:icon="@drawable/ic_launcher"
        android:showAsAction="always"
        android:title="menu">
        <menu>
            <item
                android:id="@+id/item1"
                android:showAsAction="always"
                android:title="item 1"/>
            <item
                android:id="@+id/item2"
                android:showAsAction="always"
                android:title="item 2"/>
            <item
                android:id="@+id/item3"
                android:showAsAction="always"
                android:title="item 3"/>
        </menu>
    </item>
</menu>
ab11
  • 19,770
  • 42
  • 120
  • 207
  • You can't get Click on disabled MenuItem. – Lucifer Sep 13 '12 at 15:05
  • Why not just change the text color and button action depending on a variable? Don't disable it – Mario Sep 13 '12 at 15:15
  • @mario Any suggestion on how to change MenuItem's text color? – ab11 Sep 13 '12 at 15:45
  • A simple search on SO you can find some answers, http://stackoverflow.com/questions/3519277/how-to-change-the-text-color-of-menu-item-in-android?lq=1 – Mario Sep 13 '12 at 15:51
  • @mario This solution would change the appearance of all menuitems, and also doesn't appear particularly safe for multiple os versions. – ab11 Sep 13 '12 at 16:13

1 Answers1

3

You cannot use setEnabled for this. You need to keep menu items enabled all the time and simulate the "disabled" state by changing the drawable (or modifying it using porterduff filter - have a look at this question on how to dim images in android). Separately, you need to keep a flag indicating the state of the item - tag of the menu item is a good option. Ideally, you'd have something like this:

private void setMenuItemEnable(MenuItem item, boolean enabled) {
    int curstate = ((Integer)item.getTag()).intValue();

    if(curState == 1 && enabled || curstate == 0 && !enabled) {
        return;
    }

    if(enabled) {
        ... //update image to remove dimming
        item.setTag(1);
    }
    else {
        ... //update image by dimming it
        item.setTag(0);
    }
}

Finally, in your onOptionsItemSelected() method, check the tag of the chosen menu item and either perform the action if the tag is 1 or display the toast if the tag is 0. Visually it will be just what you want, and functionally it'll do what you're after.

Community
  • 1
  • 1
Aleks G
  • 56,435
  • 29
  • 168
  • 265
  • any further suggestions on how to dim the menu item? As shown in the image above, the MenuItem is only text and the MenuItem class exposes no setTextColor or any similar method. Additionally, even if I was able to simulate a disabled appearance, I'd be concerned that different OS versions would use different disabled appearances, so my hardcoded disabled appearance is unlikely to match the one typically used by the system? – ab11 Sep 13 '12 at 15:40
  • @ab11 There is no other way. You cannot disable the item, because then you would not get the 'click' event. You can use `android.R.style` constants to simulate the disabled state to match the overall OS appearances – Aleks G Sep 13 '12 at 16:19