【问题】
折腾:
【记录】继续尝试给Android程序的右上角的ActionBar中添加三个点的选项按钮
期间,已经按照官网的教程:
Action Bar | Android Developers
去添加代码,增加menu,然后显示在ActionBar中了。
但是遇到的问题是:
对于menu的item,没有指定android:showAsAction为ifRoom的话,结果对于:
PAD来说,也还是会直接显示在ActionBar上面,而没有出现所希望出现的overflow按钮,即三个点的那个按钮;
并且,对于手机来说,由于ActionBar的空间有限,结果:
始终都显示不出来对应的menu了。。。
现在希望:
当没有指定android:showAsAction为ifRoom的时候:
可以让overflow显示出来
并且对于手机来说,也应该显示出来。
【解决过程】
1.搜:
android actionbar not show overflow
参考:
Android action bar not showing overflow – Stack Overflow
但是别人都说那种错误不太好,所以暂时不用。
2.参考:
android – Overflow Actions on ActionBar not showing – Stack Overflow
说是:
如果设备有物理上的Menu键,则overflow按钮就不会显示,这个是本身android的设计就这么定的。
3.所以去看看其给的链接:
How to force overflow menu on android actionbar compat? – Stack Overflow
但是其所给出的官网链接,就是我前面看的:
Action Bar | Android Developers
但我是没看到有这种说法啊。。。
4.再参考:
android – How to force action bar overflow icon to show – Stack Overflow
其解释的相对比较清楚。
然后对于讨论:
Issue 63377 – android – Eliminate sHasPermanentMenuKey, Or Better Support The … Overflow Affordance – Android Open Source Project – Issue Tracker – Google Project Hosting
中,也说的很清楚。
我个人意见是:
很明显,不应该依赖于物理上是否有MENU键,而决定是否显示三个点的按钮。
而应该是:
无论是否有物理按键,结果都显示三个点的overflow按钮。
然后看到评论里面的人,也是和我同样的观点。
但是反过来可以看出:
google那帮定UI的人,对于是否始终显示overflow按钮这点,不知道怎么想的
这么明显的UI的逻辑,竟然被其搞得这么复杂。。。。
哎,看来还是定规矩的人,考虑实在不周啊。。。
稍微动点脑子,都可以想到:
如果是否显示overflow需要依赖物理MENU按键的话,那么:
搞得有物理MENU和没物理MENU的手机,UI逻辑就不一致
并且有物理MENU键的手机,需要额外按一次MENU键,才能看到更多的菜单->明显很麻烦。
并且也侧面地鼓励android手机生厂商,需要去多弄个MENU键->增加物理成本
5.算了,不吐槽了。
去试试那个,hack的,强制出现overflow的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public
class
MainActivity xxx{
@Override
protected
void
onCreate(Bundle savedInstanceState) {
...
getOverflowMenu();
}
//force to show overflow menu in actionbar
private
void
getOverflowMenu() {
try
{
ViewConfiguration config = ViewConfiguration.get(
this
);
Field menuKeyField = ViewConfiguration.
class
.getDeclaredField(
"sHasPermanentMenuKey"
);
if
(menuKeyField !=
null
) {
menuKeyField.setAccessible(
true
);
menuKeyField.setBoolean(config,
false
);
}
}
catch
(Exception e) {
e.printStackTrace();
}
}
|
结果在4.2.2的PAD上,还是无法显示出来overflow。
6.换个4.1.2的手机试试,然后是可以显示出来overflow的:
所以现在结果是:
对于ActionBar空间够大的PAD来说,即使加了上述代码,但是对于用了ifRoom的话,也还是无法强制显示出来overflow的。
7.那再去试试,对于:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<
menu
xmlns:android
=
"http://schemas.android.com/apk/res/android"
>
<
item
android:id
=
"@+id/menu_discard"
android:icon
=
"@drawable/error_white"
android:orderInCategory
=
"1"
android:showAsAction
=
"ifRoom|withText"
android:title
=
"@string/discard"
/>
<
item
android:id
=
"@+id/menu_send"
android:icon
=
"@drawable/forward_white"
android:orderInCategory
=
"2"
android:showAsAction
=
"ifRoom|withText"
android:title
=
"@string/send"
/>
<
item
android:id
=
"@+id/menu_settings"
android:icon
=
"@drawable/settings"
android:orderInCategory
=
"3"
android:showAsAction
=
"withText"
android:title
=
"@string/settings"
/>
</
menu
>
|
以及加了getOverflowMenu,在PAD上效果:
然后是可以显示出来对应的overflow的:
8.另外,对于之前:
android – How to force action bar overflow icon to show – Stack Overflow
的讨论,看起来:
对于上述的hack的代码getOverflowMenu来说,即使是用于更新的4.4.的android中,应该也是无害的:
因为如果得到的menuKeyField为null的话,啥都不做,所以也是没啥副作用的。
此处倒是想去测试android 4.4的效果的,但是由于即没有4.4的实际设备,也没有4.4的支持x86加速的AVD虚拟机,所以就不去测试了。
【总结】
1.Android中的ActionBar中的那三个点的按钮,专业名字叫做:overflow button或overflow menu
2.overflow在新的Android 3.0+的系统中,默认是不显示的:
对应的:
3.想要让overflow始终都显示的话:
先去添加别的高手破解后强制overflow显示的那段代码getOverflowMenu,加到Activity的onCreate中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public
class
XxxActivity{
@Override
protected
void
onCreate(Bundle savedInstanceState) {
...
getOverflowMenu();
}
//force to show overflow menu in actionbar for android 4.4 below
private
void
getOverflowMenu() {
try
{
ViewConfiguration config = ViewConfiguration.get(
this
);
Field menuKeyField = ViewConfiguration.
class
.getDeclaredField(
"sHasPermanentMenuKey"
);
if
(menuKeyField !=
null
) {
menuKeyField.setAccessible(
true
);
menuKeyField.setBoolean(config,
false
);
}
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
|
然后接下来,要根据ActionBar是否有足够空间显示所有menu菜单,来决定menu的android:showAsAction是否添加ifRoom:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<
menu
xmlns:android
=
"http://schemas.android.com/apk/res/android"
>
<
item
android:id
=
"@+id/menu_discard"
android:icon
=
"@drawable/error_white"
android:orderInCategory
=
"1"
android:showAsAction
=
"ifRoom|withText"
android:title
=
"@string/discard"
/>
<
item
android:id
=
"@+id/menu_send"
android:icon
=
"@drawable/forward_white"
android:orderInCategory
=
"2"
android:showAsAction
=
"ifRoom|withText"
android:title
=
"@string/send"
/>
<
item
android:id
=
"@+id/menu_settings"
android:icon
=
"@drawable/settings"
android:orderInCategory
=
"3"
android:showAsAction
=
"withText"
android:title
=
"@string/settings"
/>
</
menu
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<
menu
xmlns:android
=
"http://schemas.android.com/apk/res/android"
>
<
item
android:id
=
"@+id/menu_discard"
android:icon
=
"@drawable/error_white"
android:orderInCategory
=
"1"
android:showAsAction
=
"ifRoom|withText"
android:title
=
"@string/discard"
/>
<
item
android:id
=
"@+id/menu_send"
android:icon
=
"@drawable/forward_white"
android:orderInCategory
=
"2"
android:showAsAction
=
"ifRoom|withText"
android:title
=
"@string/send"
/>
<
item
android:id
=
"@+id/menu_settings"
android:icon
=
"@drawable/settings"
android:orderInCategory
=
"3"
android:showAsAction
=
"withText"
android:title
=
"@string/settings"
/>
</
menu
>
|
MainActivity如下:
package cc.testsimpleactionbar1; import android.os.Bundle; import android.app.Activity; import android.graphics.Color; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; /** * Demo描述: * 使用ActionBar显示选项菜单 * * 背景资料: * Android手机不强制要求设备必须有Menu键,这样导致的问题是用户无法打开 * 选项菜单.但此时即可以将选项菜单设置成Action Item. * 即从Android 3.0 开始为MenuItem新增如下方法: * setShowAsAction(int actionEnum),该方法用于设置是否将该菜单栏 * 显示在ActionBar上,作为ActionItem * 参数值如下: * SHOW_AS_ACTION_ALWAYS:总是将该MenuItem显示在ActionBar上 * SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW:将该Action View折叠成普通菜单项 * SHOW_AS_ACTION_IF_ROOM:当ActionBar位置有足够空间时才显示该MenuItem * SHOW_AS_ACTION_NEVER:不将该MenuItem显示在ActionBar上 * SHOW_AS_ACTION_WITH_TEXT:将该MenuItem显示在ActionBar上,且显示该菜单项的文本 * * 当然我们最好是在xml文件中来定义菜单. * 所以在menu下的item属性中指定showAsAction属性即可 * 该属性的值和上面提到的参数值的表达形式很类似,作用是相同的 * * * 参考资料: * 1 Android疯狂讲义(第二版) * 2 http://blog.csdn.net/think_soft/article/details/7378824 * Thank you very much * * 测试说明: * 当手机处于横屏的时候,在因为ActionBar的空间有限 * 所以只会显示每个Item的图标,不会显示其title * 在横屏的时候既显示图标也显示title * */ public class MainActivity extends Activity { private TextView mTipTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); init(); } private void init(){ mTipTextView=(TextView) findViewById(R.id.tipTextView); } //生成对应的菜单,并添加到Menu中 @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.action_menu, menu); return true; } //菜单项被选中时执行该方法 @Override public boolean onOptionsItemSelected(MenuItem menuItem) { if (menuItem.isCheckable()) { menuItem.setChecked(true); } switch (menuItem.getItemId()) { case R.id.font10: mTipTextView.setTextSize(10 * 2); break; case R.id.font12: mTipTextView.setTextSize(12 * 2); break; case R.id.font14: mTipTextView.setTextSize(14 * 2); break; case R.id.font16: mTipTextView.setTextSize(16 * 2); break; case R.id.font18: mTipTextView.setTextSize(18 * 2); break; case R.id.redFont: mTipTextView.setTextColor(Color.RED); break; case R.id.greenFont: mTipTextView.setTextColor(Color.GREEN); break; case R.id.blueFont: mTipTextView.setTextColor(Color.BLUE); break; case R.id.plain_item: Toast toast = Toast.makeText(MainActivity.this, "单击了普通菜单项",Toast.LENGTH_SHORT); toast.show(); break; default: break; } return true; } }
main.xml如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/tipTextView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="可通过菜单修改文字的大小和颜色" android:textSize="16sp" android:gravity="center" /> </RelativeLayout>
action_menu.xml如下:
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:title="文字大小" android:icon="@drawable/font" android:showAsAction="always|withText"> <menu> <group android:checkableBehavior="single"> <item android:id="@+id/font10" android:title="10" /> <item android:id="@+id/font12" android:title="12" /> <item android:id="@+id/font14" android:title="14" /> <item android:id="@+id/font16" android:title="16" /> <item android:id="@+id/font18" android:title="18" /> </group> </menu> </item> <item android:id="@+id/plain_item" android:icon="@drawable/ic_launcher" android:title="普通菜单项" android:showAsAction="always|withText" /> <item android:title="设置颜色" android:icon="@drawable/color" android:showAsAction="always|withText"> <menu> <group> <item android:id="@+id/redFont" android:title="红色" /> <item android:id="@+id/greenFont" android:title="绿色" /> <item android:id="@+id/blueFont" android:title="蓝色" /> </group> </menu> </item> </menu>