我想在预ICS设备(2.3 - 2.1)上使用4.0+溢出菜单。我正在使用带ActionBarSherlock的HoloEverywhere。
我尝试了以下解决方案:
ActionBarSherlock & HoloEverywhere - Forcing Overflow?
但它不起作用,因为absForceOverflow
不存在。是在最新版本中删除了什么?我已经检查了ABS和HE库项目的R
个文件,而且该字段根本就没有。
我的应用主题设置为@style/Holo.Theme.Sherlock.Light
,这是我尝试继承的主题,并将absForceOverflow
参数集添加到true
。
答案 0 :(得分:36)
从ActionbarSherlock 4.2开始,我们失去了管理溢出菜单可见性的能力。 为了使其工作,您需要结合两种方法:
要强制Android 3.x(蜂窝)和更高版本的菜单可见性,您需要使用this hack + add check 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
预蜂窝设备的打开菜单:
ActionBarSherlock/src/com/actionbarsherlock/internal/view/menu/ActionMenuPresenter.java
,转到方法reserveOverflow
用以下内容替换原文:
public static boolean reserveOverflow(Context context){ 返回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版本提供绝对正常的溢出操作栏菜单。
答案 1 :(得分:27)
作为Siddharth Lele has pointed out,它已在最后的ABS版本中删除,以便与实际的操作栏相同。因此,乍一看放弃显示此菜单是最佳选择。
然而,在我看来,在某些设备的屏幕上显示溢出菜单而不显示其他设备是Android的Action Bar中的一个重大设计缺陷。原因如下:
在具有硬件菜单键的设备中,菜单不会显示在操作栏中。最近设备的趋势是将硬件按钮的数量减少到最小,因为它被认为更加用户友好(并且因为iphone没有按钮,所以他们复制了这个设计)。其他制造商确实包括菜单按钮,但除非你按下它,否则它是隐藏的(是的,当你不再需要灯时,它会亮起。不是明智的设计,但是当所有的按钮都关闭时,手机看起来更加iphonish)。 / p>
为了更好地理解这个含义,让我们看一个例子:
用户A
有一个带菜单键的设备。他正在使用他最喜欢的邮件客户端。配置邮件帐户的选项放在溢出菜单中,以及常用选项(帮助,关于等)。他想添加第二个帐户,但他不知道如何进入这个菜单。屏幕上没有任何信息可以帮助他意识到该怎么做。
因此,用户A
会询问他的朋友B
,他也在使用此邮件客户端。用户B
拥有最新的Nexus N + 1 Googlephone,并且他可以在操作栏中查看溢出图标,因为他的设备没有使用硬件菜单键。他显示A
如何通过打开此菜单添加第二个帐户。用户A
现在完全混淆了,因为他们使用相同的应用版本。沮丧,A
可能会认为问题在于他的手机太老了。 B
也被混淆了。
此时您可能会认为A
和B
都是无法理解如何使用智能手机的傻瓜。但与桌面应用程序不同,绝大多数智能手机用户不了解其设备的基础知识。他们以前的手机很可能是一个带有简单固件的键盘设备。电池坏了,他们去了商店替换,但它缺货了。他们本可以在互联网上订购一台,但它比购买新手机更贵。所以他们卖了一部支持触摸屏的手机,因为这就是现在的手机。现在,他们必须面对一台拥有完整操作系统的小型计算机。更糟糕的是,手机只有一个“快速入门指南”,要获得完整的手册,他们必须从互联网上下载pdf。你猜怎么着?他们不会。
如果您正在开发移动应用程序,您应该假设用户可能不了解有关计算机,操作系统或类似应用程序的事情。您应该使GUI在各种设备上看起来相似,以便人们可以学习并记住如何使用它。不要责怪Action Bar设计师:如果用户喜欢A
或B
,那么首先不知道如何进入选项菜单这是你的错误。这就是为什么你应该包括一个始终可见的选项屏幕的方法。
后退键发生了类似的事情。某些设备可能具有HW后备密钥,较新的设备通常不具备。但每当我们回到我们的应用程序时,我们总是在Action Bar中显示箭头状按钮,对吧?是的,我知道一个按钮在“导航树”中导航,而另一个按钮“回到过去”,但这也是另一个设计缺陷:对于普通用户,后面只是回来了。他在屏幕上有这个按钮,他也可以使用HW,但这是可选的。应该使用溢出菜单完成相同的操作。
所以如果你认为(像我一样)这是一个重要的按钮,不要放弃。 提供常规主选项菜单并使用相关子菜单填充。将其设为操作按钮并为其指定描述性图标,甚至是“MENU”等文本说明。您还可以模仿溢出菜单图标,只需使用其中一个drawable:
// 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
此外:将图像复制粘贴到项目资源文件夹中。您永远无法知道ABS的未来版本或ActionBar的下一个实现是否会包含它们。
答案 2 :(得分:18)
如果您使用的是版本4.2.0,那么.ForceOverflow
主题实际上已被删除。
更改日志的摘录:
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>
在Activity
中为manifest.xml
应用主题时,我将其用作属性:"@style/Theme.SociallyYOU"
同样,如果你必须绝对强制溢出,你可能还想在另一个问题中阅读CommonsWare的想法:https://stackoverflow.com/a/12872537/450534。
注意:话虽如此,如果权衡不重要,最好使用最新版本。通过发布我强制溢出菜单的方式,我既不建议您使用旧版本,也不建议使用旧版本。它只是告诉你可能性。
答案 3 :(得分:0)
我发现Exterminator13的答案在某些Android设备上不起作用(我认为总数很小),但为了适应尽可能多的设备,我使用对话框并使用一个菜单与android:showAsAction = “总是”作为溢出菜单按钮。毕竟,actionbarsherlock的溢出菜单的效果是通过它的来源实现的,所以如果它不那么麻烦,为什么不实现我们自己的效果。如果您了解中文,您还可以看到my blog。
<?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();
}