16

Im using action bar compability library. Im trying to open the options menu from a button with openOptionsMenu() function but it does nothing.

Menu shows as usual when pressing the menu key on my phone. What is wrong here?

public class ReadActivity extends ActionBarActivity {

    ...

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        boolean value;
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.read, menu);
        value = super.onCreateOptionsMenu(menu);

        if (Helper.SupportsNewApi()) {
            getActionBar().hide();
        } else {
            ((View) ((LinearLayout) findViewById(R.id.actionbar_compat))
                    .getParent()).setVisibility(View.GONE);
        }

        return value;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            finish();
            break;
        case R.id.menu_search:
            // Toast.makeText(this, "Tapped search", Toast.LENGTH_SHORT).show();
            break;
        case R.id.menu_bookmark:
            // selectText();
            // setFullScreen(false);
            break;
        case R.id.menu_day_night_mode:
            break;
        case R.id.menu_settings:
            break;
        case R.id.menu_zoom_in:
            showOverlay(false);
            break;
        case R.id.menu_zoom_out:
            showOverlay(false);
            break;
        case R.id.menu_table_of_contents:
            Intent tocIntent = new Intent(this, TocActivity.class);
            int GET_SECTION_REFERENCE = 1;
            startActivityForResult(tocIntent, GET_SECTION_REFERENCE);
            break;
        case R.id.menu_overflow:
            Toast.makeText(this, "Tapped overflow", Toast.LENGTH_SHORT).show();

            //closeOptionsMenu();
            openOptionsMenu(); //tried the below aswell, no results
            //getWindow().openPanel(Window.FEATURE_OPTIONS_PANEL, null);
            break;
        }
        return super.onOptionsItemSelected(item);
    }


    @Override //disable volume buttons
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (!menuShown && (keyCode == 25 || keyCode == 24)) {
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        Log.d(tag, "Keycode is = "+keyCode);
        if (keyCode == 82) {
            if (!menuShown) {
                //openOptionsMenu();
                showOverlay(true);
            } else {
                showOverlay(false);
            }


                    //don't want it to open when pressing menu
            return true;
        } else if (keyCode == 4 && menuShown) {
            showOverlay(false);
            return true;
        } else if (keyCode == 25 && !menuShown) {
            prevPage();
            return true;
        } else if (keyCode == 24 && !menuShown) {
            nextPage();
            return true;
        }

        return super.onKeyUp(keyCode, event);
    }

}
Richard
  • 14,427
  • 9
  • 57
  • 85
  • this post [http://stackoverflow.com/questions/18937711/openoptionsmenu-not-working-with-actionbarsherlock-custom-submenu][1] is work for me. [1]: http://stackoverflow.com/questions/18937711/openoptionsmenu-not-working-with-actionbarsherlock-custom-submenu – Holding Fish Aug 13 '14 at 03:15

8 Answers8

32

I was having the same problem trying to go around this openOptionsMenu thing on an app that I was doing that should run on Android 1.6 and up. Following the answer from Werner Van Belle I reached the conclusion that we could achieve a workaround to solve the problem. So I came up with the following code, it's always beatiful when people don't mark a method as final, so we can always override it. It's perfect if you don't want to give up on targeting your app to the latest api (android:targetSdkVersion="17"). I hope you guys like it. :)

@Override
public void openOptionsMenu() {

    Configuration config = getResources().getConfiguration();

    if((config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) 
            > Configuration.SCREENLAYOUT_SIZE_LARGE) {

        int originalScreenLayout = config.screenLayout;
        config.screenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
        super.openOptionsMenu();
        config.screenLayout = originalScreenLayout;

    } else {
        super.openOptionsMenu();
    }
}
tallicalord
  • 329
  • 3
  • 2
  • 1
    That's terrible! It's also the only solution that works. Thanks! – benkc Nov 21 '13 at 19:56
  • This doesn't work for my app on a 3.2 device targeting API 17. On click of a button, I call openOptionsMenu() and the method in the answer gets executed. But still I don't get the Options Menu. I wonder how it works for the previous commenters. Am I missing something? Do we need to override any other methods (onCreateOptionsMenu, onPrepareOptionsMenu)? – MediumOne Nov 28 '13 at 07:27
  • 2
    How _can_ this work ? You cannot simply modify the Configuration variable. When you call the parent super.openOptionsMenu it will still retrieve its own resources, which will tell it that is is a large screen again. So I wonder whether you really tested this ? And if so and it did work... then I'm pretty sure it is not supposed to work like that and it might pretty much break at any moment. –  Dec 19 '13 at 19:52
  • Werner Van Belle, I agree with you that this should not work. But I have tested this myself and surprisingly the menu does show again. – Twinsen Jan 06 '14 at 08:21
  • 1
    Magic! This answer should be marked as the correct one. Thanks – jbc25 Jan 15 '14 at 11:39
  • It works since in the Android code they read this property, and if your target version is Honeycomb or up and you are on an xlarge screen, then it doesn't call the menu methods (onCreate/PrepareOptionsMenu). You can see it in the PhoneWindow.java code in the openPanel method there is the following comment: Don't open an options panel for honeycomb apps on xlarge devices (The app should be using an action bar for menu items.) – Yoel Gluschnaider Feb 11 '14 at 16:28
  • This works on my Lollypop tablet too. Great! Werner's points regarding Google's railroading of developers was spot on. – Andrew S Jun 23 '15 at 02:08
  • Thanks! I'll be giving this a try. Can you add a few words of explanation as to how and why this works? – Edward Falk Aug 08 '15 at 23:43
  • 2
    I hate that Android broke such a basic functionality as menus on what amounts to a whim. Yes, I know that Action Bar is the way of the future, but I have legitimate reasons why I can't use it. The bottom line is that I know better than the Android developers how my app is supposed to look and feel. Menus worked just fine for me until recently and I'm getting complaints from paying customers now that it's broken. All they had to do was *not* break it. – Edward Falk Aug 09 '15 at 00:01
9

To shed some light on this sad development by google. Google obviously wishes everybody to embrace the new ActionBar. They could have achieved that by making the ActionBar easier to use than the old menu system. That is however not how they planned the transition. No, they thought it would make sense to harras programmers by making the old menus impossible to use but without providing proper backward compatibility.

Below is the code taken from com.android.internal.policy.impl, which is supposed to create the optionsMenu panel. As you see, the code simply refuses to create an options Panel. Allthough, the ability is obviously there. So, to answer your question: forget it, Google doesn't want you to use that optionsPanel anymore.

 // Don't open an options panel for honeycomb apps on xlarge devices.
 // (The app should be using an action bar for menu items.)
 if (st.featureId == FEATURE_OPTIONS_PANEL) {
            Context context = getContext();
            Configuration config = context.getResources().getConfiguration();
            boolean isXLarge = (config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) ==
                    Configuration.SCREENLAYOUT_SIZE_XLARGE;
            boolean isHoneycombApp = context.getApplicationInfo().targetSdkVersion >=
                    android.os.Build.VERSION_CODES.HONEYCOMB;

            if (isXLarge && isHoneycombApp) {
                return;
            }
        }
  • 2
    It seems once again with Google that usability is the excuse, but not the agenda. Well done for digging this out and enlightening us. – Andrew S Jun 23 '15 at 02:09
  • Action Bar is perfectly easy to use, the problem is that some of us have perfectly legitimate reasons not to use it and menus worked just fine for us before. – Edward Falk Aug 09 '15 at 00:07
4

I cannot understand the forcing blocking Menu button usage as well. However, the following trick helped me with showing a menu on "restricted" types of devices.

First of all we need to define, whether we require the following hack or not.

boolean requireDirtyMenuButtonHack = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && (activity.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_XLARGE) > 0;

Then:

protected final OnClickListener mMenuButtonClickListener = new OnClickListener() {

    @Override
    public void onClick(View v) {
        if (requireDirtyMenuButtonHack) {
            Configuration config = getContext().getResources().getConfiguration();
            config.screenLayout &= ~Configuration.SCREENLAYOUT_SIZE_XLARGE;
            config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_LARGE;
        }

        getActivity().openOptionsMenu();
    }
};

Don't forget to cleanup! (don't know if it's neccessary, but better to play kind)

public void onPrepareOptionsMenu(Menu menu) {
    if (requireDirtyMenuButtonHack) {
        Configuration config = getContext().getResources().getConfiguration();
        config.screenLayout &= ~Configuration.SCREENLAYOUT_SIZE_LARGE;
        config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_XLARGE;
    }

    //do the preparing...
}
snuk182
  • 1,022
  • 1
  • 12
  • 28
3

I'm not sure how relevant this is, but this forum post I found seems to be answerring the same question you have.

I hope this post is relevant enough to solve your problem.

Good luck!

Macarse
  • 91,829
  • 44
  • 175
  • 230
Wottah
  • 320
  • 2
  • 13
  • 1
    How did this solved the issue? I don't believe it is really related. – htafoya Aug 30 '13 at 16:31
  • 6
    It is related, but answers should contain an answer, not merely a link to an answer on another site. – mhsmith Nov 19 '13 at 23:44
  • 2
    Just in case some one is still looking this is the real answer on that forum post "Maybe you on the Android Team should make a fricking consistent API that works across devices so we can't shoot ourselves in the FOOT everytime you release and change behaviour or add some huge new thing out of the blue." – dipu Jul 30 '14 at 05:27
  • 1
    I'm still looking at it, and yes it's no end of grief for me. I wrote a simple calculator app. Screen real-estate is precious to me and I simply cannot have a title bar or an action bar. Originally I just set the Target API to 2.2 and everything worked until one damn device decided to make the menu button a floating button and it floated right over the '+' sign in my calculator. So I switched my target API to 4.0 and there's been no end of trouble since. There is simply no way to just display a menu in Android any more. – Edward Falk Aug 08 '15 at 23:37
  • Anyway, the official answer from Mark Murphy in that thread seems to be "If you don't have an an action bar then you can't have a menu." Although oddly enough it seems to work on *most* of the devices I'm trying to support. – Edward Falk Aug 08 '15 at 23:38
  • And this is why you quote relevant parts of any linked content! The link is broken and this answer is now useless. – Eugen Pechanec Dec 26 '18 at 11:12
2

android:targetSdkVersion="10" in manifest helped me. openOptionsMenu() works as expected now on ICS+. In addition, there is "overflow" menu button appears at the bottom of screen (on device buttons panel).

ps: I use NoTitleBar theme (NoActionBar for sdk 11 and higher) +ViewPagerIndicator by Jake Wharton.

deviant
  • 3,539
  • 4
  • 32
  • 47
2

This worked for me, my code is pretty similar to yours, and what I want to do is from a button in the action bar, open the overflow menu:

public boolean onOptionsItemSelected(MenuItem item) {  
        switch (item.getItemId()) {  
        case R.id.menu_home_about:  
            dialog = new Dialog(this);
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setContentView(R.layout.customdialog);
            dialog.show();
            break;

            default:

        case R.id.menu_home_refresh:
            updateLists(true);
            break;

        case R.id.menu_home_menu:
            new Handler().postDelayed(new Runnable() {
                public void run() {                
                    openOptionsMenu();        
                }
            }, 0); 
            return true;

        }
        return false;  
    }
htafoya
  • 18,261
  • 11
  • 80
  • 104
0

If you are using your custom toolbar, you can try:

toolBar.showOverflowMenu();
taskinoor
  • 45,586
  • 12
  • 116
  • 142
0

Do you mean you want to show a button on the right side of the action bar?

Here is how I did mine:

res/menu/main.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_share"
    android:title="Logout"
    android:icon="@android:drawable/ic_lock_power_off"
    android:orderInCategory="1"
    android:showAsAction="always" />
</menu>

Activity
1) take note of the ActionBarActivity; 2) MenuInflater in onCreateOptionsMenu 3) onOptionsItemsSelected (I think you need to return super.onOptionsItemSelected(item) )

public class BaseActivity extends ActionBarActivity {
    ....

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

    return true;
}
....
@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
    case R.id.menu_share:


       //Do something
        break;
    }

    return super.onOptionsItemSelected(item);
}
Mark Pazon
  • 6,167
  • 2
  • 34
  • 50
  • No the actionbar and menu is inflated and added correctly. It's the ´openOptionsMenu()´ function called from a button that does nothing! – Richard Apr 03 '12 at 15:33