26

我希望在 ICS 之前的设备 (2.3 - 2.1) 上使用 4.0+ 溢出菜单。我将 HoloEverywhere 与 ActionBarSherlock 一起使用。

我尝试了以下解决方案:

ActionBarSherlock & HoloEverywhere - 强制溢出?

但它不起作用,因为absForceOverflow不存在。它是在最新版本中删除还是什么?我检查了RABS 和 HE 库项目的文件,但该字段根本不存在。

我的应用程序的主题设置为@style/Holo.Theme.Sherlock.Light,这是我试图继承并将absForceOverflow参数集添加到的主题true

4

4 回答 4

36

从 ActionbarSherlock 4.2 开始,我们失去了管理溢出菜单可见性的能力。要使其正常工作,您需要结合两种方法:

  1. 要强制 Android 3.x (honeycomb) 及更高版本的菜单可见性,您需要使用hack + 添加检查 Android 版本:

    public static final int DEVICE_VERSION   = Build.VERSION.SDK_INT;
    public static final int DEVICE_HONEYCOMB = Build.VERSION_CODES.HONEYCOMB;
    if (DEVICE_VERSION >= DEVICE_HONEYCOMB)
        // Code from answer above
    
  2. 预蜂窝设备的打开菜单:

    • 打开ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java,转到方法reserveOverflow
    • 将原件替换为:

      public static boolean reserveOverflow(Context context) { return true; }

    这将强制菜单显示...

    • 但是当点击菜单按钮菜单弹出不显示。为此,我们需要在您的活动类中覆盖它:

      @Override
      public boolean onKeyUp(int keyCode, KeyEvent event) {
          if (DEVICE_VERSION < DEVICE_HONEYCOMB) {
              if (event.getAction() == KeyEvent.ACTION_UP &&
                  keyCode == KeyEvent.KEYCODE_MENU) {
                  openOptionsMenu();
                  return true;
              }
          }
          return super.onKeyUp(keyCode, event);
      }
      

在此操作之后,您应该拥有适用于所有 Android 版本的绝对有效的溢出操作栏菜单。

于 2012-11-26T15:33:53.453 回答
27

正如Siddharth Lele 所指出的,它已在最后一个 ABS 版本中被删除,以便与实际的 Action Bar 表现相同。所以乍一看放弃显示这个菜单是最好的选择。

但是,在我看来,某些设备的屏幕上显示溢出菜单而其他设备不显示是 Android 操作栏的一个重大设计缺陷。原因如下:

在具有硬件菜单键的设备中,菜单不会显示在操作栏中。最近设备的趋势是将硬件按钮的数量减少到最低限度,因为它被认为对用户更友好(并且因为 iphone 只有一个按钮,所以他们复制了这种设计)。其他制造商确实包含菜单按钮,但它是隐藏的,除非你按下它(是的,当你不再需要灯时它会亮起。这不是一个明智的设计,但同样,当所有按钮都关闭时,手机看起来更 iphonish)。

为了更好地理解这一点,让我们看一个例子: 用户A有一个带有菜单键的设备。他正在使用他最喜欢的邮件客户端。配置邮件帐户的选项与常用选项(帮助、关于等)一起放置在溢出菜单中。他想添加第二个帐户,但不知道如何访问此菜单。屏幕上没有任何信息可以帮助他意识到该做什么。所以用户A问他的朋友B,他也在使用这个邮件客户端。用户B拥有最新的 Nexus N+1 Googlephone,并且他能够在操作栏中查看溢出图标,因为他的设备没有硬件菜单键。他展示A了如何通过打开此菜单添加第二个帐户。用户A现在完全糊涂了,因为他们使用的是相同的应用程序版本。沮丧,A可能会认为问题出在他的手机太旧了。B也很困惑。

在这一点上,您可能会同时考虑两者A,并且B是不知道如何使用智能手机的傻瓜。但与桌面应用程序不同的是,绝大多数智能手机用户只知道他们设备的基础知识。他们以前的手机很可能是一个带有简单固件的键盘设备。电池没电了,他们去商店换了,但没货了。他们本可以在互联网上订购一个,但它比购买一部新手机要贵。因此,他们出售了一款支持触摸屏的手机,因为这就是如今的手机。现在他们必须面对一台配备成熟操作系统的小型计算机。更糟糕的是,这款手机只附带“快速入门指南”,要获得完整的手册,他们必须从互联网上下载 pdf。你猜怎么了?他们不会。

如果您正在开发移动应用程序,您应该假设用户可能对计算机、操作系统或类似应用程序一无所知。您应该使 GUI 在不同设备上看起来相似,以便人们可以学习并记住如何使用它。不要责怪 Action Bar 设计者:如果用户喜欢AB不知道如何进入选项菜单,那首先是你的错。这就是为什么您应该包含一种访问始终可见的选项屏幕的方法。

后退键也会发生类似的事情。有些设备可能有硬件返回键,较新的设备通常没有。但是每当我们可以返回我们的应用程序时,我们总是会在操作栏中显示那个类似箭头的按钮,对吧?是的,我知道一个按钮在“导航树”中导航,而另一个按钮“回到过去”,但这也是另一个设计缺陷:对于普通用户来说,返回只是返回。他在屏幕上有这个按钮,他也可以使用硬件按钮,但这是可选的。溢出菜单也应该这样做。

因此,如果您(像我一样)认为这是一个重要的按钮,请不要放弃。提供一个常规的主选项菜单并用相关的子菜单填充它。将其设为操作按钮并为其分配一个描述性图标,甚至是像“菜单”这样的文字描述。您还可以模仿溢出菜单图标,只需使用以下可绘制对象之一:

    // For ActionBarSherlock
    abs__ic_menu_moreoverflow_normal_holo_dark.png
    abs__ic_menu_moreoverflow_normal_holo_light.png

    // For ActionBar
    ic_menu_moreoverflow_normal_holo_light.png
    ic_menu_moreoverflow_normal_holo_dark.png

此外:将图像复制粘贴到您的项目 res 文件夹中。您永远无法知道 ABS 的未来版本或 ActionBar 的下一个实现是否会包含它们。

于 2012-11-12T09:49:04.800 回答
19

如果您使用的是 4.2.0 版,那么.ForceOverflow主题实际上已被删除。

来源: 版本 4.2.0 变更日志

变更日志摘录:

Add SearchView widget for standard search interaction (API 8+ only)
Fix: ShareActionProvider in the split action bar no longer fills the entire screen.
Fix: ShareActionProvider now does file I/O on a background thread.
Fix: Automatically correct ColorDrawable not respecting bounds when used as a stacked background.
Fix: Ensure fragments collection is present before dispatching events.
Fix: XML-defined onClick searches the correct context for the declared method.
Fix: Ensure action mode start/finish callbacks are invoked on the activity for the native action bar.
Fix: Allow tab callbacks to have a fragment transaction instance for any FragmentActivity.
Fix: Ensure CollapsibleActionView callbacks are dispatched in both native and compatbility action bars.
Fix: Remove .ForceOverflow themes. These never should have been included.

如果您绝对需要强制溢出,则需要下载早期版本的 ABS。您可以在此处根据其发布历史获取下载列表:http: //actionbarsherlock.com/download.html

我个人仍然使用 ABS 版本 4.1.0,因为我目前不想在我的应用程序中进行辅助更改。我也在我的theme.xml

<style name="MyTheme" parent="@style/Theme.Sherlock.ForceOverflow">
    <item name="android:windowBackground">@color/background</item>
    <item name="actionBarStyle">@style/Widget.Styled.ActionBar</item>
    <item name="android:actionBarStyle">@style/Widget.Styled.ActionBar</item>
</style>

<style name="MyTheme.ForceOverflow">
    <item name="absForceOverflow">true</item>
</style>

在为 中的 an 应用主题时Activitymanifest.xml我将其用作属性:"@style/Theme.SociallyYOU"

同样,如果您必须绝对强制溢出,您可能还想在此处的另一个问题中阅读 CommonsWare 的想法:https ://stackoverflow.com/a/12872537/450534 。

注意:话虽如此,如果权衡并不重要,最好使用最新版本。通过发布我如何强制溢出菜单,我既不建议您使用旧版本,也不建议您这样做。它只是告诉你可能性。

于 2012-11-01T15:28:29.927 回答
0

我发现 Exterminator13 的答案在某些类型的 Android 设备上不起作用(我认为总数很小),但为了适应尽可能多的设备,我使用对话框并使用带有 android:showAsAction="always" 的菜单作为溢出菜单按钮。毕竟actionbarsherlock的溢出菜单的效果是通过源码实现的,如果不是那么麻烦,何不自己实现效果呢。如果你懂中文,也可以看看我的博客

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/more"
        android:icon="@drawable/overflow"
        android:showAsAction="always" 
    />
</menu>

 

private Dialog popupDialog;
private Boolean popupState=false;

    public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        this.finish();
        return true;
    case R.id.more:
        if (!popupState) {
            showPop();
        }else {
            popupDialog.dismiss();
        }
    default:
        return super.onOptionsItemSelected(item);
    }
}

private void showPop(){
    LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View view = inflater.inflate(ResID, null);
    ListView listView = (ListView) view.findViewById(ResID);
    listView.setAdapter(yourOwnAdapter);
    popupDialog = new Dialog(WifiAuthWireActivity.this);
    popupDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    popupDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.WHITE));
    popupDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    popupDialog.setContentView(view);
    // Calculate ActionBar height
    TypedValue tv = new TypedValue();
    ActionBar maActionBar=getSupportActionBar();
    int actionBarHeight=maActionBar.getHeight();
    if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
    {
        actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
    }
    WindowManager.LayoutParams wmlp = popupDialog.getWindow().getAttributes();
    wmlp.gravity = Gravity.TOP | Gravity.RIGHT;
    wmlp.x+=12;
    wmlp.y+=actionBarHeight;
    popupDialog.getWindow().setAttributes(wmlp);
    popupDialog.show();
}
于 2013-11-02T15:44:58.747 回答