Steve Moseley
Steve Moseley

Reputation: 5877

openOptionsMenu() will not work in appcompat-v7 22.1.0 or newer

I've seen several reports of issues where openOptionsMenu() will not work on various Android versions, eg:

openOptionsMenu() across android versions

openOptionsMenu() not working

but the issue I have seems to be related to the version of the appcompat-v7 support library being used.

In essence, with the newer versions of appcompat-v7 the menu will appear fine when openOptionsMenu() is called if your activity extends Activity but will not work if you extend ActionBarActivity or AppCompatActivity (ie use the compatibility library). In older versions of appcompat-v7 it works fine.

It is reproducible, as follows:

  1. In Android Studio, Import Sample 'ActionBarCompat-Basic'
  2. Add a button to the screen, which invokes openOptionsMenu()
  3. Note that this works fine, as the old version of the library, appcompat-v7:21.0.3 is used in the sample
  4. Change the dependency to use appcompat-v7:23.0.1, rebuild, and when clicking on the button the menu will not appear.
  5. Change the main activity to extend Activity (ie no app compatability) - it works
  6. Change the main activity to extend AppCompatActivity (ie using app compatibility libarry) - it fails

After some testing, I've found that this stopped working in appcompat-v7:22.1.0, and will no longer work in any newer version of this jar.

This behaviour is identical on the emulator and on a physical device, and on Android versions 5.1.1(23) and 2.1(7) which were the two versions I tested it with.

I've added a comment to this bug: Android issue tracker bug

Any suggestions, ideas or workarounds appreciated!

-Steve

Upvotes: 11

Views: 2170

Answers (2)

Carlos Gómez
Carlos Gómez

Reputation: 357

More simple than The Wanderer's post and it goes fine in genymotion and also in my cell phone (marshmallow):

import android.support.v7.widget.Toolbar;

//btMainMenu is a button
public void btMainMenu_click(View view) {
    final View view2 = getWindow().getDecorView().findViewById(R.id.action_bar);
    if (view2 instanceof Toolbar) {
        ((Toolbar) view2).showOverflowMenu();
    }
    else {
        System.out.println("What a pity!, it doesn't work..., view2 is not toolbar");
    }
}

https://issuetracker.google.com/issues/37060139

Upvotes: 0

TheWanderer
TheWanderer

Reputation: 17844

I think I may have actually found a workaround for this. It involves overriding the openOptionsMenu() method:

@Override
public void openOptionsMenu()
{
    mActionBar.showOverflowMenu();
}

In order for showOverflowMenu() to work on devices with a physical menu key that are below API 19, use this: How to force action bar overflow icon to show

mActionBar is assigned as such:

android.support.v7.widget.Toolbar mActionBar = (android.support.v7.widget.Toolbar) getActionBar(getWindow().getDecorView())

This is the getActionBar() method:

public static ViewGroup getActionBar(View view)
{
    try
    {
        if (view instanceof ViewGroup)
        {
            ViewGroup viewGroup = (ViewGroup) view;

            if (viewGroup instanceof android.support.v7.widget.Toolbar)
            {
                return viewGroup;
            }

            for (int i = 0; i < viewGroup.getChildCount(); i++)
            {
                ViewGroup actionBar = getActionBar(viewGroup.getChildAt(i));

                if (actionBar != null)
                {
                    return actionBar;
                }
            }
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    return null;
}

Calling openOptionsMenu() from an AppCompatActivity now works!

NOTE: I tested this on API 26, but seeing as the getActionBar() method works far below that, I see no reason the rest of this will fail.

Upvotes: 3

Related Questions