14

I want to do a custom action when pressing on the Menu button on the phone.

Is it possible to set an onClickListener (or similar) on the button and if so, how?

onCreateOptionsMenu is only called the first time the button is pressed - I've already tried this.

Mat Nadrofsky
  • 8,289
  • 8
  • 49
  • 73
whlk
  • 15,487
  • 13
  • 66
  • 96

4 Answers4

30

Usually you shouldn't override MENU behavior as users expect menu to appear, however you can use something along these lines:

/* (non-Javadoc)
 * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
 */
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if ( keyCode == KeyEvent.KEYCODE_MENU ) {
        Log.d(TAG, "MENU pressed");
        return true;
    }
    return super.onKeyDown(keyCode, event);
}
Diego Torres Milano
  • 65,697
  • 9
  • 111
  • 134
  • 1
    Thanks - this is what I was looking for. And dont worry - I'm not gona change the user experience but i want to do some custom actions before the menu is actually rendered. – whlk Mar 22 '10 at 09:34
  • yanchenko has a better solution. – katzenhut Aug 22 '14 at 12:55
19

But onPrepareOptionsMenu(..) is called each time. :)

yanchenko
  • 56,576
  • 33
  • 147
  • 165
  • 1
    Not a very long answer, but this is the way to do it! As he said, it's called every time before the menu actually appears, so you can customise your menu in that. – Steve Haley Mar 19 '10 at 15:58
  • Seems that for me it is not called everytime ! the first or second time it's called but then not. it is as if android knows it already prepared the menu and its in memory so it will not prepare it again. – Mercury Apr 03 '17 at 23:22
3

Updated for AppCompat v.22.+

As mentioned in this forum, KeyDown is not called for KEYCODE_MENU button pressed.

The solution is to override dispatchKeyEvent to this way:

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    int keyCode = event.getKeyCode();
    int action = event.getAction();
    boolean isDown = action == KeyEvent.ACTION_DOWN;

    if (keyCode == KeyEvent.KEYCODE_MENU) {
        return isDown ? this.onKeyDown(keyCode, event) : this.onKeyUp(keyCode, event);
    }

    return super.dispatchKeyEvent(event);
}

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {

    if ( keyCode == KeyEvent.KEYCODE_MENU ) {
        // do what you want to do here
        return true;
    }

    return super.onKeyDown(keyCode, event);
}

It works until Google developers release a fix for this (or maybe it is not a bug and it works this way from now on).

Jon Willis
  • 6,993
  • 4
  • 43
  • 51
danigonlinea
  • 1,113
  • 1
  • 14
  • 20
  • 2
    broken in appcompat 22.1.x and at least 22.2.1 see: https://code.google.com/p/android/issues/detail?id=159795#c20 – Jon Willis Jul 31 '15 at 01:15
1

You could probably hack something in using "OnMenuOpened" or some such, but I really wouldn't recommend it. The menu button is only supposed to be used to show menus, so there is consistency between applications.

Cheryl Simon
  • 46,552
  • 15
  • 93
  • 82