1

I have an actionbar with a menu. When you click the button, the menu shows up and all is well with the world.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:id="@+id/reload" 
        android:title="@string/reload" 
        android:alphabeticShortcut="r" 
        android:numericShortcut="1" 
        android:titleCondensed="Rload"></item>

    <group android:id="@+id/adv" android:menuCategory="secondary">
        ...options
    </group>
</menu>

However, I just got told that we have a client whose device has some sort of other menu bar that is displayed over the current one so they can't access the menu. So I added a button on the webview with a javascriptinterface to tell my Activity to display the menu programmatically. I can get there just fine, but I can't for the life of me figure out how to display the menu as if the menu button was pressed.

I tried doing something like this:

private void showMenu() {
    try{
        actionbar.show();
        MenuItem menu = (MenuItem) findViewById(R.id.adv);
        menu.expandActionView();
    }
    catch(Exception e){
        Log.e(LOG_CAT,"Unable to inflate menu");
    }
}

but I'm getting a null pointer exception

java.lang.NullPointerException: Attempt to invoke interface method 'boolean android.view.MenuItem.expandActionView()' on a null object reference

It seems like what I'm trying to do should be trivially easy, but it may be that I'm just doing something boneheaded instead.

EDIT I don't actually want to just show R.id.adv, I would like to show the whole menu so that should probably be findViewById(R.menu.menu_main) instead, where menu_main is the name of the file that the above xml is defined in.

S. Buda
  • 727
  • 7
  • 27

1 Answers1

2

findViewById looks in the view hierarchy of the activity, not the menu. You need to get the items you need right after your menu is created:

Edit:

Didn't think it's possible but it is. With the help of this answer here's how you can do it:

View mOverflow;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final View decor = getWindow().getDecorView();
    decor.post(new Runnable() {
        @Override
        public void run() {
            ArrayList<View> results = new ArrayList<>();
            decor.findViewsWithText(results, "OVERFLOW",
                    View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);

            if (results.size() == 1) {
                mOverflow = results.get(0);
            }
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

private void showMenu() {
    actionbar.show();
    mOverflow.performClick();
}

And in your styles.xml:

<style name="AppTheme" parent="android:Theme.Holo">
    <item name="android:actionOverflowButtonStyle">@style/Widget.ActionButton.Overflow</item>
</style>

<style name="Widget.ActionButton.Overflow" parent="@android:style/Widget.Holo.ActionButton.Overflow">
    <item name="android:contentDescription">OVERFLOW</item>
</style>

findViewsWithText requires API 14+, however the answer I linked, has a solution for lower APIs.

Community
  • 1
  • 1
Simas
  • 43,548
  • 10
  • 88
  • 116
  • That makes sense to me, but menu.findItem(R.id.adv); is still returning a null object. Looking at the object in the debugger, it seems like the menu object I'm getting in onCreateOptionsMenu is actually the object I want displayed. – S. Buda Jan 14 '15 at 19:10
  • @S.Buda are you sure `showMenu` is not called before the menu is created? – Simas Jan 14 '15 at 19:16
  • Yes. `showMenu` is only called when a user presses a certain button, but `onCreateOptionsMenu` is called at application start. – S. Buda Jan 14 '15 at 19:20
  • @S.Buda is your ActionBar hidden by default? – Simas Jan 14 '15 at 19:26
  • Possibly, within my `onCreate` function I create the actionbar and then I hide it. – S. Buda Jan 14 '15 at 19:29
  • Interesting, it isn't throwing errors anymore, but it still isn't doing anything. – S. Buda Jan 14 '15 at 19:37
  • @S.Buda can you be more specific? Perhaps you should make the group hidden by default in your xml: `android:visible="false"`. – Simas Jan 14 '15 at 19:38
  • When the `showMenu` function is called, it no longer has a null object. `mMenu` is definitely defined. Setting the group to visible simply does nothing. It appears that the `setGroupVisible` only effects whether the items are in the menu when it is displayed. – S. Buda Jan 14 '15 at 19:48
  • @S.Buda well it does seem to answer "Programmatically display actionbar item". – Simas Jan 14 '15 at 19:49
  • Well, no, because it doesn't show the actionbar item. It only toggles whether it's visible when the user presses the actual menu button on the actionbar. Also, I did add something else to my question, though I think it's mostly an inane change if I can get your suggestion to actually work. – S. Buda Jan 14 '15 at 19:51
  • @S.Buda you mean you want to be able to hide all the items but not the actionbar itself? – Simas Jan 14 '15 at 19:52
  • I guess what I mean is that your suggestion is able to hide and show the items within the list, but that requires the list to be open to begin with. I want to open the list programmatically, not toggle whether or not the items show within it. – S. Buda Jan 14 '15 at 19:54
  • @S.Buda oh you meant the overflow (usually three vertical dot button) menu in your actionbar? – Simas Jan 14 '15 at 19:57
  • Right, so I want that to be displayed when a button on my webview is pressed. – S. Buda Jan 14 '15 at 20:32