I asked this question 6 years ago. In the meantime Android development best practices have changed, and I have become a better developer.
Since then, I have realized that using the onClick XML attribute is a bad practice, and have removed it from any code base I work on.
All of my click handlers are now defined in the code of the app, not the XML layouts!
My reasons for never using onClick are
it is easy to make a mistake in the value of the onClick XML attribute, which will then result in a run-time error
a developer might refactor the name of the click handler method, without realizing it is called from a layout (see reason 1)
finding out which method is actually being called is not always obvious. Especially if the layout is being used by a Fragment
separating the concerns of layout vs behavior is good. Using onClick mixes them up, which is bad!
I hope I have convinced you to never use onClick in a layout :) !
Below is my original question, which is a pretty good illustration of why using onClick is a bad idea.
===
I'm defining menu items in XML, and trying to use the onClick attribute that was added in API 11. When the Activity is launched in an emulator running 4.0.3, the following Exceptions occur:
FATAL EXCEPTION: main
android.view.InflateException: Couldn't resolve menu item onClick handler
onFeedbackMenu in class android.view.ContextThemeWrapper
...
Caused by: java.lang.NoSuchMethodException: onFeedbackMenu
[interface com.actionbarsherlock.view.MenuItem]
at java.lang.Class.getConstructorOrMethod(Class.java:460)
I don't understand what is causing the Exception, since the following method is defined in my Activity
import com.actionbarsherlock.view.MenuItem;
...
public void onFeedbackMenu( MenuItem menuItem ) {
Toast.makeText( this, "onFeedBack", Toast.LENGTH_LONG ).show();
}
My XML menu definition file contains:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
...
<item
android:id="#+id/menu_feedback"
android:icon="#drawable/ic_action_share"
android:showAsAction="ifRoom"
android:title="#string/menu_feedback"
android:onClick="onFeedbackMenu" />
</menu>
For backwards compatibility I am using ActionBarSherlock, and also getting a very similar Exception when I run the App on 2.3.x.
This is a more Complete version of the Stack trace
FATAL EXCEPTION: main
android.view.InflateException: Couldn't resolve menu item onClick handler
onFeedbackMenu in class android.view.ContextThemeWrapper
at com.actionbarsherlock.view.MenuInflater$InflatedOnMenuItemClickListener.<init>(MenuInflater.java:204)
at com.actionbarsherlock.view.MenuInflater$MenuState.setItem(MenuInflater.java:410)
at com.actionbarsherlock.view.MenuInflater$MenuState.addItem(MenuInflater.java:445)
at com.actionbarsherlock.view.MenuInflater.parseMenu(MenuInflater.java:175)
at com.actionbarsherlock.view.MenuInflater.inflate(MenuInflater.java:97)
...
Caused by: java.lang.NoSuchMethodException: onFeedbackMenu
[interface com.actionbarsherlock.view.MenuItem]
at java.lang.Class.getConstructorOrMethod(Class.java:460)
at java.lang.Class.getMethod(Class.java:915)
at com.actionbarsherlock.view.MenuInflater$InflatedOnMenuItemClickListener.<init>(MenuInflater.java:202)
... 23 more
I found a solution that worked for me.
Usually the onClick attribute in a layout has the following method
public void methodname(View view) {
// actions
}
On a menu item (in this case Sherlock menu) it should follow the following signature:
public boolean methodname(MenuItem item) {
// actions
}
So, your problem was that your method returned void and not boolean.
In my case, the AndroidManifest.xml of my application (kick-started by the default Eclipse assistant) contained android:theme="#style/AppTheme" in the <application> block.
When debugging the cause of the problem, it turned out that the line
mMethod = c.getMethod(methodName, PARAM_TYPES);
in android.view.MenuInflater/InflatedOnMenuItemClickListener was called with c not being my Activity class but a dubious android.view.ContextThemeWrapper (which of course doesn't contain the onClick handler).
So, I removed the android:theme and everything worked.
Although this is a bit out of date, here is the reason for the exception. When you look into the sources of android API 15 (4.0.3-4.0.4) in the class MenuInflater you will see this method:
public InflatedOnMenuItemClickListener(Context context, String methodName) {
mContext = context;
Class<?> c = context.getClass();
try {
mMethod = c.getMethod(methodName, PARAM_TYPES);
} catch (Exception e) {
InflateException ex = new InflateException(
"Couldn't resolve menu item onClick handler " + methodName +
" in class " + c.getName());
ex.initCause(e);
throw ex;
}
This is were the exception happens, as Junique already pointed out. However the removing of the app theme is just a workaround and no real option. As we see the method tries to find the Callback method on the class of the context item passed. So instead of calling getMenuInflater() in onCreateOptionsMenu you should call new MenuInflater(this), so that this is passed as a context and then the code will work.
You can still use getMenuInflater() for other api versions if you just use an if statement like this:
if (Build.VERSION.SDK_INT > 15)
inflater = getMenuInflater();
else
inflater = new MenuInflater(this);
I don't actually know if the bug happens in api versions under 15 too, so i just generally used the save version.
In my case the problem was that I had both onClick in my menu XML and an onCreateOptionsMenu in my Activity. My onClick was actually faulty (because it pointed to non-existent methods) but I didn't notice this at first because I was testing under Android 2.x, where onClick is not supported and ignored. Once I tested on 4.x though, I started getting this error.
So basically, don't use onClick if you plan on deploying under Android 2.x. It will silently ignore your onClick values until you try running on 3.0+.
I found that I had the same problem with the ActionBar menu items, and their onClick events. What i discovered is that the workstation I'm developing in had run out of memory and needed to be rebooted. The Android VM is now able to resolve the method name referenced.
Your method must accept a MenuItem as its only parameter per here.
public void onMenuItemClickMethod(MenuItem menuItem){
// Do stuff here
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
MenuItem item = menu.findItem(R.id.menu_open);
if (item == null)
return true;
item.setOnMenuItemClickListener
(
new MenuItem.OnMenuItemClickListener ()
{
public boolean onMenuItemClick(MenuItem item)
{ return (showDirectory(item)); }
}
);
return true;
}
public boolean showDirectory (MenuItem item)
{
CheckBox checkBox = (CheckBox) findViewById (R.id.checkBox1);
checkBox.setChecked(true);
}
Related
I am writing here about an issue that was introduced when we migrated from the AppCompat library to the AndroidX library. While doing so, we switched from android.support.design.widget.NavigationView to com.google.android.material.navigation.NavigationView and that’s when the following issue started.
In our NavigationView design, in order to save space, we implemented an expandable menu, so that when users clicks on the “more” button, the menu expands to show more options. It starts off with only some options visible, and the rest are not visible, as follows;
Option 1
Option 2
More…
Upon clicking on the “More...” button, the menu expands to;
Option 1
Option 2
Option 3
Option 4
Option 5
Option 6
To do this we used following code;
#Override
public boolean onNavigationItemSelected(MenuItem item)
{
....
if (item.getItemId() == R.id.nav_more)
{
item.setVisible(false); // hide the “More” item
getMenu().findItem(R.id.nav_option_3).setVisible(true);
getMenu().findItem(R.id.nav_option_4).setVisible(true);
getMenu().findItem(R.id.nav_option_5).setVisible(true);
getMenu().findItem(R.id.nav_option_6).setVisible(true);
return true;
}
.......
return false;
}
Well, this code has worked in the past, but when we migrated to using the androidx library, poof, it stopped working. Well, it did work a bit. The “More...” button got hidden, but the previously hidden options, were not being displayed.
As, it took me many hours to solve this issue, and to save others this headache, I will explain the issue and the solution.
The first thing to do in such cases, is to look at the source code. As the code is open source, I was able to get it at github. At first glance I didn’t get smarter. I found that the NavigationView has a NavigationMenuPresenter object field (called presenter), that has a method called updateMenuView() which calls adapter.update(), which calls prepareMenuItems() and notifyDataSetChanged(). This sounded like the needed fix, so using reflection, we accessed and called the updateMenuView() method, but surprisingly, it did not help!
So, I decided to take it to the extreme, and see what happens if I call getMenu().clear(), and believe it or not, nothing happened. It seems that any changes made to Menu after the NavigationView is shown, are ignored. But a quick look through source code, I could not see any reason for that.
So how do I solve this issue? I tried using the latest alpha version of the library, but I still have the same issue.
Well, after much work, I found the solution. It's actually simple. Just hold on for the answer.
Lionscribe
So I was back to the source code, searching for some clue, when I fell upon a method called setUpdateSuspended(boolean updateSuspended). Well, that sounded suspicious! I searched for usage of this method, and found it being called in the onClick callback. Here is a minimized version of the code;
#Override
public void onClick(View view) {
NavigationMenuItemView itemView = (NavigationMenuItemView) view;
setUpdateSuspended(true);
MenuItemImpl item = itemView.getItemData();
boolean result = menu.performItemAction(item, NavigationMenuPresenter.this, 0);
setUpdateSuspended(false);
}
Bingo! It seems that while handling clicks, the NavigationView suspends and will not recognize any changes done to menu. I am not sure the reason for this, but as we were updating the menu in the onNavigationItemSelected callback, which is called by the onClick method, the menu updates are ignored.
Well, once I understood the issue, the solution was simple and clean. I just wrapped the code in a Runnable, and posted it, so that it runs after the onClick method returns, and setUpdateSuspended is set back to false. Here is the updated code;
#Override
public boolean onNavigationItemSelected(MenuItem item)
{
....
if (item.getItemId() == R.id.nav_more)
{
final MenuItem itemFinal = item;
post(new Runnable()
{
#Override
public void run()
{
getMenu().findItem(R.id.nav_option_3).setVisible(true);
getMenu().findItem(R.id.nav_option_4).setVisible(true);
getMenu().findItem(R.id.nav_option_5).setVisible(true);
getMenu().findItem(R.id.nav_option_6).setVisible(true);
itemFinal.setVisible(false); // hide the “More” item
}
});
return true;
}
.......
return false;
}
Viola! The expandable menu now works like it used to, the hidden items are now being shown!
I hope this will be of help to others with same issue.
Lionscribe
I have the below espresso test:
openActionBarOverflowOrOptionsMenu(InstrumentationRegistry.getTargetContext());
// if I Thread.sleep() here, I can see that the MenuItem has been clicked already
onView(withText("Sign in")) //<= click on the MenuItem
.perform(click());
onView(withId(R.id.signupButton)) //<= click the signup button in my UI
.perform(click());
The first line up there opens the overflow menu and clicks the first item at the same time (which happens to be the signin item). So the test fails because it cannot find the MenuItem view. Is there anything I am doing wrong ? I am using an emulator API 22, compiling agains targetSdk 24 and using espresso 2.2.1.
Try that:
public class EspressoMatchers {
public static Matcher<View> withOverflowMenuButton() {
return anyOf(allOf(isDisplayed(), withContentDescription("More options")),
allOf(isDisplayed(), withClassName(endsWith("OverflowMenuButton"))));
}
}
To open overflow menu:
onView(allOf(EspressoMatchers.withOverflowMenuButton(),
isDescendantOfA(withId(R.id.toolbar)))).perform(click());
Then it should work fine. Just use right ID for your Toolbar. I know this is just a copy from Espresso class, but I also ran into this issue and this helped me.
Please remember to always click the menu items "by name", not by their ID, as ID won't work. So your "click item" should be fine:
onView(withText("Sign in")) //<= click on the MenuItem
.perform(click());
I am trying to create an app for android and I came across the following problem:
The application crashes in a specific phone when I press the menu button. Let me give you some details first.
The bug occurs to ONLY on LG Optimus L3 II e430 with Android 4.1.2 (tested on four other phones so far)
The application starts with a splash screen and no action bar. At this point menu button just doesn't do anything.
With a simple touch we get past the splash screen and we go to the Main Activity which implements ActionBar activity and has a navigation drawer.
From this point and after, every time I try to click on the menu button the app crashes.
Here is the layout of the menu and the onCreateOptionsMenu function:
res/menu/main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/action_settings"
android:title="#string/action_settings"
android:orderInCategory="100"
app:showAsAction="never" />
</menu>
Part from MainActivity.java
#Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.main, menu);
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
Please note that this code is generated from Android Studio.
So far what I've tried:
Tried to look at the file that has the problem from the sdk sources (API Level 16 and 21) but they were not relevant to the stack trace (line shown in the stack trace pointed in a location that didn't make sense).
Tried to install XPosed fix for Google PlayStore crash with menu button bug. Nothing here either.
Found a similar bug report to firefox's bugtracking system so I tried to install Firefox and see if it crashes on my phone when I press Menu Button; firefox didn't crash. (Link to firefox's bug)
Here is the stack trace from LogCat:
10-24 09:08:02.710 4712-4712/com.scaryboxstudios.unrealestateapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at com.android.internal.policy.impl.PhoneWindow.onKeyUpPanel(PhoneWindow.java:1004)
at com.android.internal.policy.impl.PhoneWindow.onKeyUp(PhoneWindow.java:1712)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2125)
at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3611)
at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:3581)
at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:2831)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4929)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565)
at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
at dalvik.system.NativeStart.main(Native Method)
Update: With Appcompat-v7 version 22.0.0, onKeyUp does not seem to fire for the Menu key. The original bug appears to be fixed, so I will likely remove the submenu workaround. Unfortunately I haven't verified the fix on an affected LG 4.1 device.
I ended up doing a workaround for this, which users are reporting has fixed the issue for them.
Implement submenus instead of relying on the overflow menu. The caveat to this is that now every device will see the overflow button in the Action Bar even if they have a Menu key.
The following technique is from https://stackoverflow.com/a/18530179/57490
Convert all overflow options menu items to submenus.
Override onKeyUp in your Activities, have it call Menu.performIdentifierAction(R.id.menu_overflow, 0); and do not call super.onKeyUp for keyCode == KEYCODE_MENU.
After stumbling upon the same problem recently I found the root of the problem. The problem is compatibility issues between older and newer support libraries. It seems that I used depreciated stuff around my code together with newer stuff.
I am sorry for being kind of abstract but this question is 4 months old and I cannot remember what exactly were the incorrect lines of code. If memory serves right, the problem lied upon auto generated methods from Android Studio for application drawer activities. I used the Drawer Application project template from Android Studio and I chose to support very old Android APIs too so Android Studio chose the depreciated Android Support Library.
The point is that I resolved the problem when I refactored the code to use non depreciated techniques only.
If you are fighting against a similar problem I strongly recommend remove everything that Android Studio (I assume that you use Android Studio or Eclipse) marks as depreciated.
Also for catching Menu button can use next:
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) {
// TODO - Your user code
/*
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0) {
// Tell the framework to start tracking this event.
//getKeyDispatcherState().startTracking(event, this);
return true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
// getKeyDispatcherState().handleUpEvent(event);
if (event.isTracking() && !event.isCanceled()) {
// DO BACK ACTION HERE
return true;
}
}*/
// if you don't want use system listener
// return super.dispatchKeyEvent(event);
return false;
} else {
return super.dispatchKeyEvent(event);
}
}
Worked for lastest AppCompat and SDK version - 22.0
I have an EditText and I want the user to be able to select some text and apply some basic formatting to the selected text (bold, italic, etc). I still want the standard copy, cut, paste options to show, though. I read somewhere in the Android documentation that to do this, you should call setCustomSelectionActionModeCallback() on the EditText and pass it an ActionModeCallback(), so that's what I did. Here's my code:
In my activity's onCreate() method:
myEditText.setCustomSelectionActionModeCallback(new TextSelectionActionMode());
Callback declaration:
private class TextSelectionActionMode implements ActionMode.Callback {
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
menu.add("Bold");
return true;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
}
The problem I'm having is that when I click on the overflow button (to access my "Bold" menu item), the ActionMode gets closed immediately. If I set it to always show as an action, using this:
MenuItem bold = menu.add("Bold");
bold.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS);
It works fine and I can click on it (though it obviously does nothing). What am I missing here?
Edit: Just wanted to add that I run into the exact same problem if I actually inflate a menu instead of adding menu items programmatically. Once again, though, the problem goes away if I force it to always show as an action.
It's frameworks issue. If textview receive 'focus changed' event, then textview stop the action mode. When overflow popup is shown, textview miss focus.
This issue has been solved in Android 6.0. However you should use ActionMode.Callback2 as described here in Android 6.0.
For Android 5.x and below, I recommend this workaround: add a button to Toolbar or ActionBar which records the current selection and then open another context menu.
this.inputText_selectionStart = inputText.getSelectionStart();
this.inputText_selectionEnd = inputText.getSelectionEnd();
registerForContextMenu(inputText);
openContextMenu(inputText);
unregisterForContextMenu(inputText);
It is a filed Android bug: https://code.google.com/p/android/issues/detail?id=82640.
That link contains a workaround. Fortunately this has been fixed in Android 6.0.
I'd like to have all of the menu items that don't fit into the ActionBar go into the overflow menu (the one that is reached from the Action Bar not the menu button) even on devices that do have a Menu button. This seems much more intuitive for users than throwing them into a separate menu list that requires the user to jump from a touch(screen) interaction to a button based interaction simply because the layout of the ActionBar can't fit them on the bar.
On the emulator I can set the "Hardware Back/Home Keys" value to "no" and get this effect.
I've searched for a way to do this in code for an actual device that has a menu button but can't fine one. Can anyone help me?
You can also use this little hack here:
try {
ViewConfiguration config = ViewConfiguration.get(this);
Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
if (menuKeyField != null) {
menuKeyField.setAccessible(true);
menuKeyField.setBoolean(config, false);
}
} catch (Exception ignored) {
}
Good place to put it would be the onCreate-Method of your Application class.
It will force the App to show the overflow menu. The menu button will still work, but it will open the menu in the top right corner.
[Edit] Since it has come up several times now: This hack only works for the native ActionBar introduced in Android 3.0, not ActionBarSherlock. The latter uses its own internal logic to decide whether to show the overflow menu. If you use ABS, all platforms < 4.0 are handled by ABS and are thus subjected to its logic. The hack will still work for all devices with Android 4.0 or greater (you can safely ignore Android 3.x, since there aren't really any tablets out there with a menu button).
There exists a special ForceOverflow-Theme that will force the menu in ABS, but apperently it is going to be removed in future versions due to complications.
EDIT: Modified to answer for the situation of physical menu button.
This is actually prevented by design. According to the Compatibility Section of the Android Design Guide,
"...the action overflow is available from the menu hardware key. The resulting actions popup... is displayed at the bottom of the screen."
You'll note in the screenshots, phones with a physical menu button don't have an overflow menu in the ActionBar. This avoids ambiguity for the user, essentially having two buttons available to open the exact same menu.
To address the issue of consistency across devices: Ultimately it's more important to the user experience that your app behave consistently with every other app on the same device, than that it behave consistently with itself across all devices.
I use to workaround it by defining my menu like this (also with ActionBarSherlock icon used in my example):
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+id/menu_overflow"
android:icon="#drawable/abs__ic_menu_moreoverflow_normal_holo_light"
android:orderInCategory="11111"
android:showAsAction="always">
<menu>
<item
android:id="#+id/menu_overflow_item1"
android:showAsAction="never"
android:title="#string/overflow_item1_title"/>
<item
android:id="#+id/menu_overflow_item2"
android:showAsAction="never"
android:title="#string/overflow_item2_title"/>
</menu>
</item>
</menu>
I admit that this may require manual "overflow-management" in your xml, but I found this solution useful.
You can also force device to use HW button to open the overflow menu, in your activity:
private Menu mainMenu;
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO: init menu here...
// then:
mainMenu=menu;
return true;
}
#Override
public boolean onKeyUp(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
if (mainMenu !=null) {
mainMenu.performIdentifierAction(R.id.menu_overflow, 0);
}
}
return super.onKeyUp(keycode, e);
}
:-)
If you are using the action bar from the support library (android.support.v7.app.ActionBar), use the following:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yorapp="http://schemas.android.com/apk/res-auto" >
<item
android:id="#+id/menu_overflow"
android:icon="#drawable/icon"
yourapp:showAsAction="always"
android:title="">
<menu>
<item
android:id="#+id/item1"
android:title="item1"/>
<item
android:id="#+id/item2"
android:title="item2"/>
</menu>
</item>
</menu>
This kind of method is prevented by the Android Developers Design System, but I found a way to pass it:
Add this to your XML menu file:
<item android:id="#+id/pick_action_provider"
android:showAsAction="always"
android:title="More"
android:icon="#drawable/ic_action_overflow"
android:actionProviderClass="com.example.AppPickActionProvider" />
Next, create a class named 'AppPickActionProvider', and copy the following code to it:
package com.example;
import android.content.Context;
import android.util.Log;
import android.view.ActionProvider;
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.SubMenu;
import android.view.View;
public class AppPickActionProvider extends ActionProvider implements
OnMenuItemClickListener {
static final int LIST_LENGTH = 3;
Context mContext;
public AppPickActionProvider(Context context) {
super(context);
mContext = context;
}
#Override
public View onCreateActionView() {
Log.d(this.getClass().getSimpleName(), "onCreateActionView");
return null;
}
#Override
public boolean onPerformDefaultAction() {
Log.d(this.getClass().getSimpleName(), "onPerformDefaultAction");
return super.onPerformDefaultAction();
}
#Override
public boolean hasSubMenu() {
Log.d(this.getClass().getSimpleName(), "hasSubMenu");
return true;
}
#Override
public void onPrepareSubMenu(SubMenu subMenu) {
Log.d(this.getClass().getSimpleName(), "onPrepareSubMenu");
subMenu.clear();
subMenu.add(0, 1, 1, "Item1")
.setIcon(R.drawable.ic_action_home).setOnMenuItemClickListener(this);
subMenu.add(0, 2, 1, "Item2")
.setIcon(R.drawable.ic_action_downloads).setOnMenuItemClickListener(this);
}
#Override
public boolean onMenuItemClick(MenuItem item) {
switch(item.getItemId())
{
case 1:
// What will happen when the user presses the first menu item ( 'Item1' )
break;
case 2:
// What will happen when the user presses the second menu item ( 'Item2' )
break;
}
return true;
}
}
Well I think that Alexander Lucas has provided the (unfortunately) correct answer so I'm marking it as the "correct" one. The alternative answer I'm adding here is simply to point any new readers to this post in the Android Developers blog as a rather complete discussion of the topic with some specific suggestions as to how to deal with your code when transitioning from pre-level 11 to the new Action Bar.
I still believe it was a design mistake not have the menu button behave as a redundant "Action Overflow" button in menu button enabled devices as a better way to transition the user experience but its water under the bridge at this point.
I'm not sure if this is what you're looking for, but I built a Submenu within the ActionBar's Menu and set its icon to match the Overflow Menu's Icon. Although it wont have items automatically sent to it, (IE you have to choose what's always visible and what's always overflowed) it seems to me that this approach may help you.
In the gmail app that comes with ICS pre-installed, the menu button is disabled when you have multiple items selected. The overflow menu is here "forced" to be triggered by the use of the overflow button instead of the physical menu button. Theres a 3rd-party lib called ActionBarSherlock which lets you "force" the overflow menu. But this will only work on API level 14 or lower(pre-ICS)
If you use Toolbar, you can show the overflow on all versions and all devices, I've tried on some 2.x devices, it works.
Sorry if this problem is dead.
Here is what I did to resolve the error. I went to layouts and created two ones containing toolbars. One was a layout for sdk version 8 and the other was for sdk version 21. On version 8, I used the android.support.v7.widget.Toolbar while I used android.widget.Toolbar on the sdk 21 layout.
Then I inflate the toolbar in my activity. I check the sdk to see if it was 21 or higher. I then inflate the corresponding layout. This forces the hardware button to map onto the toolbar you actually designed.
For anyone using the new Toolbar:
private Toolbar mToolbar;
#Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
...
}
#Override
public boolean onKeyUp(int keycode, KeyEvent e) {
switch(keycode) {
case KeyEvent.KEYCODE_MENU:
mToolbar.showOverflowMenu();
return true;
}
return super.onKeyUp(keycode, e);
}