Answers:
编辑:修改以回答物理菜单按钮的情况。
实际上,这是通过设计防止的。根据《 Android设计指南》的“ 兼容性”部分,
“ ...操作溢出可通过菜单硬件键获得。弹出的操作弹出窗口将显示在屏幕底部。”
您会在屏幕截图中注意到,带有物理菜单按钮的手机在ActionBar中没有溢出菜单。这避免了用户的歧义,本质上具有两个按钮可用来打开完全相同的菜单。
要解决跨设备的一致性问题:从根本上说,对于用户体验而言,您的应用程序与同一设备上的所有其他应用程序始终保持一致,比其在所有设备上与其自身始终保持一致的行为更为重要。
您还可以在这里使用此小技巧:
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) {
}
放置它的好地方将是 onCreate
Application类 -Method。
它将强制应用程序显示溢出菜单。菜单按钮仍然可以使用,但是它将打开右上角的菜单。
[编辑]由于它已经出现了好几次了:此hack仅适用于Android 3.0中引入的本机ActionBar,不适用于ActionBarSherlock。后者使用自己的内部逻辑来决定是否显示溢出菜单。如果使用ABS,所有<4.0平台均由ABS处理,因此要遵守其逻辑。该破解程序仍适用于所有搭载Android 4.0或更高版本的设备(您可以放心地忽略Android 3.x,因为实际上并没有带有菜单按钮的平板电脑)。
存在一个特殊的ForceOverflow-Theme主题,它将强制在ABS中显示菜单,但是由于复杂性,它将在以后的版本中删除。
Field
选择java.lang.reflect.Field
;)
我过去通过定义这样的菜单来解决该问题(在示例中也使用了ActionBarSherlock图标):
<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>
我承认这可能需要在您的xml中进行手动“溢出管理”,但是我发现此解决方案很有用。
您还可以在活动中强制设备使用硬件按钮打开溢出菜单:
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);
}
:-)
如果要使用支持库(android.support.v7.app.ActionBar
)中的操作栏,请使用以下命令:
<?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>
Android Developers Design System阻止了这种方法,但是我找到了一种方法:
将此添加到您的XML菜单文件:
<item android:id="@+id/pick_action_provider"
android:showAsAction="always"
android:title="More"
android:icon="@drawable/ic_action_overflow"
android:actionProviderClass="com.example.AppPickActionProvider" />
接下来,创建一个名为“ AppPickActionProvider”的类,并将以下代码复制到该类:
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;
}
}
我认为亚历山大·卢卡斯提供了(不幸的)正确答案,因此我将其标记为“正确”答案。我要在此处添加的替代答案只是将任何新读者指向Android开发者博客中的这篇文章作为对该主题的相当完整的讨论,并提出了一些有关从预备级别11过渡时如何处理代码的具体建议。到新的操作栏。
我仍然认为这是一个设计错误,没有菜单按钮在启用菜单按钮的设备中充当多余的“动作溢出”按钮,这是转移用户体验的一种更好的方法,但在此时此刻它是无处不在的。
在预装有ICS的gmail应用中,如果您选择了多个项目,则菜单按钮将被禁用。溢出菜单在这里被“强制”通过使用溢出按钮而不是物理菜单按钮来触发。有一个第三方库,称为ActionBarSherlock,可让您“强制”溢出菜单。但这仅适用于API级别14或更低版本(ICS之前的版本)
如果您使用工具栏,则可以在所有版本和所有设备上显示溢出,我已经在某些2.x设备上尝试过,它可以正常工作。
对于使用新功能的任何人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);
}