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

Pau*_*ulP 158 android android-actionbar

我想让所有不适合ActionBar的菜单项都进入溢出菜单(从操作栏到菜单按钮),即使在有菜单按钮的设备上也是如此.对于用户而言,这似乎更直观,而不是将它们放入单独的菜单列表中,该列表要求用户从触摸(屏幕)交互跳转到基于按钮的交互,这仅仅是因为ActionBar的布局不能适合他们在栏上.

在模拟器上,我可以将"硬件后退/主页键"值设置为"否"并获得此效果.我已经在代码中搜索了一种方法来实现具有菜单按钮但不能很好的设备的实际设备.谁能帮我?

Tim*_*Ohr 323

你也可以在这里使用这个小黑客:

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) {
}
Run Code Online (Sandbox Code Playgroud)

放置它的好地方onCreate是你的Application类的方法.

它将强制App显示溢出菜单.菜单按钮仍然有效,但它会打开右上角的菜单.

[编辑]因为它现在出现了好几次:这个hack只适用于Android 3.0中引入的原生ActionBar,而不适用于ActionBarSherlock.后者使用自己的内部逻辑来决定是否显示溢出菜单.如果使用ABS,所有平台<4.0都由ABS处理,因此受其逻辑的影响.黑客仍然适用于Android 4.0或更高版本的所有设备(你可以安全地忽略Android 3.x,因为没有任何平板电脑带有菜单按钮).

存在一个特殊的ForceOverflow-Theme将强制ABS中的菜单,但由于复杂性,它将在未来版本中被删除.

  • 美丽!如果Eclipse为你提供了6种不同的导入供``Field`选择这个`java.lang.reflect.Field`;) (18认同)
  • 我查看了源代码.无证特征的宝藏树林:)只要确保你有类似的东西可行的后备. (4认同)
  • 非常感谢!这真的很棒.我想将评论,错误报告和共享操作放入溢出,但它没有在Nexus S上显示.用户甚至不会单击"菜单"按钮.随着溢出用户看到额外的操作可用. (4认同)
  • @Ewoks我在这里发表评论的时间已经很晚了,但我只是用最新版本的ActionBarCompat尝试了这个,而且DID也可以. (4认同)
  • 这适用于三星Galaxy S3和S4,但不适用于LG G2(怀疑他们是硬编码检查显示溢出菜单按钮) (3认同)
  • 很好的发现,在Galaxy S3上创造奇迹. (2认同)

Ale*_*cas 54

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

这实际上是通过设计来防止的.根据Android设计指南兼容性部分,

"...操作溢出可从菜单硬件键获得.弹出的操作弹出...显示在屏幕底部."

您将在屏幕截图中注意到,带有物理菜单按钮的手机在ActionBar中没有溢出菜单.这避免了用户的模糊性,基本上有两个按钮可用于打开完全相同的菜单.

解决跨设备一致性的问题:最终,用户体验更重要的是,您的应用程序与同一设备上的每个其他应用程序的行为一致,而不是在所有设备上与其自身的行为一致.

  • 让我们进入这个对话并讨论:我知道它被设计阻止了(我阅读了设计指南).但我认为那就是%$ /%#+.例如:用户正在从Galaxy Nexus( - > w Overflow)切换到Nexus One(w 4.0/ - > no Overflow).我打赌用户将不再找到菜单项.出于这个原因,我想要对所有设备使用相同的用法.所以,我最终遇到了和paulp一样的问题.有没有可用的干净的解决方法? (41认同)
  • 谷歌在他们的新谷歌+应用程序中反对这一点.它有溢出项目,无论设备如何..但据我所知,它们仍然阻止开发人员做同样的事情并提出建议. (18认同)
  • 我也先阅读设计指南.对我来说,这是支持包中糟糕的设计选择.将用户从按钮转移的更好策略(目标,对吗?)将使其变得多余,将功能放在屏幕上以及按钮中.就像现在一样,按钮不会列出所有菜单选项,只列出那些不在操作栏上的菜单选项,因此这个设计既不支持平滑过渡到操作栏,也不支持在添加操作栏之前做的事情(显示**全部**菜单选择).我怀疑你是对的,并没有简单的解决方法. (10认同)
  • 老实说,我已经看到太多的用户没有尝试菜单硬键以期望他们.如果设计说任何手机上的任何用户都不应该有屏幕指示器存在菜单选项,那么该设计是一个信息不足的设计. (10认同)

Ber*_*ťák 35

我通过像这样定义我的菜单(也使用我的例子中使用的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>
Run Code Online (Sandbox Code Playgroud)

我承认这可能需要在你的xml中手动"溢出管理",但我发现这个解决方案很有用.

您还可以强制设备在您的活动中使用HW按钮打开溢出菜单:

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);
}
Run Code Online (Sandbox Code Playgroud)

:-)

  • 如何使用HW按钮打开溢出菜单? (2认同)

a f*_*yer 11

如果您使用支持库(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>
Run Code Online (Sandbox Code Playgroud)


Eli*_*vah 7

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" />
Run Code Online (Sandbox Code Playgroud)

接下来,创建一个名为"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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Pau*_*ulP 5

好吧,我认为Alexander Lucas提供了(不幸的)正确的答案,所以我将其标记为"正确的"答案.我在这里添加的替代答案只是将任何新读者指向Android开发者博客中的这篇文章作为对该主题的相当完整的讨论,并提供一些关于如何在从11级前转换时处理代码的具体建议到新的Action Bar.

我仍然认为这是一个设计错误,没有菜单按钮在菜单按钮启用的设备中表现为冗余的"动作溢出"按钮,作为转换用户体验的更好方式,但此时它在桥下的水.