Android 如何在带有菜单按钮的设备上强制使用溢出菜单

Android 如何在带有菜单按钮的设备上强制使用溢出菜单,android,android-actionbar,Android,Android Actionbar,我希望所有不适合操作栏的菜单项都进入溢出菜单(从操作栏而不是菜单按钮到达的菜单项),即使在没有菜单按钮的设备上也是如此。对于用户来说,这似乎比将他们放入一个单独的菜单列表更直观,因为操作栏的布局不适合他们,所以需要用户从触摸(屏幕)交互跳到基于按钮的交互 在模拟器上,我可以将“硬件返回/主密钥”值设置为“否”,并获得此效果。 我已经在一个实际的设备的代码中寻找了一种方法来实现这一点,该设备有一个菜单按钮,但不能确定一个。有人能帮我吗?编辑:修改为回答物理菜单按钮的情况 这实际上是被设计所阻止的。

我希望所有不适合操作栏的菜单项都进入溢出菜单(从操作栏而不是菜单按钮到达的菜单项),即使在没有菜单按钮的设备上也是如此。对于用户来说,这似乎比将他们放入一个单独的菜单列表更直观,因为操作栏的布局不适合他们,所以需要用户从触摸(屏幕)交互跳到基于按钮的交互

在模拟器上,我可以将“硬件返回/主密钥”值设置为“否”,并获得此效果。
我已经在一个实际的设备的代码中寻找了一种方法来实现这一点,该设备有一个菜单按钮,但不能确定一个。有人能帮我吗?

编辑:修改为回答物理菜单按钮的情况

这实际上是被设计所阻止的。据报道,

“…操作溢出可从菜单硬件键获得。产生的操作弹出…显示在屏幕底部。”

你会在截图中注意到,带有物理菜单按钮的手机在ActionBar中没有溢出菜单。这避免了用户的歧义,基本上有两个按钮可以打开完全相同的菜单


解决跨设备的一致性问题:最终,对于用户体验来说,你的应用程序与同一设备上的所有其他应用程序的行为一致比它在所有设备上的行为一致更重要。

我认为Alexander Lucas提供了(不幸的是)答案正确,所以我把它标为“正确”答案。我在这里添加的另一个答案是简单地向任何新读者指出,这是一个关于这个主题的相当完整的讨论,并提供了一些具体的建议,说明在从前11级过渡到新的操作栏时如何处理代码


我仍然认为这是一个设计错误,没有让菜单按钮在菜单按钮支持的设备中表现为冗余的“动作溢出”按钮,这是一种更好的过渡用户体验的方式,但在这一点上,它是一种桥下之水。

在预装ICS的gmail应用程序中,当您选择了多个项目时,菜单按钮将被禁用。溢出菜单在这里是通过使用溢出按钮而不是物理菜单按钮来“强制”触发的。有一个称为ActionBarSherlock的第三方库,它允许您“强制”溢出菜单。但这只适用于API级别14或更低(ICS之前)

我不确定这是否是您想要的,但我在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
-方法

它将强制应用程序显示溢出菜单。菜单按钮仍将工作,但它将打开右上角的菜单

[编辑]因为它已经出现过好几次了:这种攻击只适用于Android 3.0中引入的本机ActionBar,而不是ActionBarSherlock。后者使用自己的内部逻辑来决定是否显示溢出菜单。如果您使用ABS,所有<4.0的平台都由ABS处理,因此受其逻辑约束。这项技术仍然适用于所有使用安卓4.0或更高版本的设备(你可以安全地忽略安卓3.x,因为实际上没有任何带有菜单按钮的平板电脑)


存在一个特殊的ForceOverflow主题,它将强制ABS中的菜单,但显然是这样。

Android开发者设计系统阻止了这种方法,但我找到了一种方法来传递它:

将其添加到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" />

我通常通过这样定义菜单来解决这个问题(在我的示例中还使用了ActionBarSherlock图标):


:-)

如果您正在使用支持库中的操作栏(
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>

如果使用,您可以在所有版本和所有设备上显示溢出,我已经在一些2.x设备上尝试过,它可以正常工作。

如果此问题已经解决,请道歉

以下是我为解决此错误所做的操作。我转到布局,创建了两个包含工具栏的布局。一个是sdk版本8的布局,另一个是sdk版本21的布局。在版本8上,我使用了android.support.v7.widget.Toolbar,而在sdk21布局上使用了android.widget.Toolbar


然后我在活动中展开工具栏。我检查sdk是否为21或更高。然后对相应的布局进行充气。这将强制硬件按钮映射到您实际设计的工具栏上。

对于使用新的
工具栏的用户:

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);
}

Alexander-不,我已经尝试了所有showAsAction值和几个组合,但没有一个能奏效(至少在模拟器上是这样)。只有在模拟没有菜单按钮的设备时,操作栏上的溢出菜单才会显示。我想看到垂直省略号,并有溢出的项目显示在有菜单按钮的设备上。我对我的问题进行了编辑,使之更清晰。让我们进入这个对话并讨论:我知道设计会阻止它(我阅读了设计指南)。但我认为这有点像%$/%#+。例如:用户正在从Galaxy Nexus(->w溢出)切换到Nexus One(w 4.0/->无溢出)。我打赌用户再也找不到菜单项了。出于这个原因,我希望所有设备的使用都相同。所以,我的问题和paulp一样。没有干净的解决方法吗?我也先看了设计指南。对我来说,在支持包中这是一个糟糕的设计选择。一个更好的策略,让用户远离按钮
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);
}
<?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>
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);
}