怎么让android系统中隐藏的menu按钮显示出来
来源:互联网 发布:python 和js 编辑:程序博客网 时间:2024/04/27 22:21
问题?
在将项目工程最小sdk版本和target版本提高的14之后,也就是最低支持4.0之后,menu按键在系统上显示不出来了,对于某些资深android玩家来说这点是比较坑爹的。
那么下面就是解决问题的过程了。
如需转载 注明转自http://blog.csdn.net/luoxiaozhuo/article/details/50592567
查询phonewindow的源码可以看到这样一段代码
3335 final Context context = getContext();3336 final int targetSdk = context.getApplicationInfo().targetSdkVersion;3337 final boolean targetPreHoneycomb = targetSdk < android.os.Build.VERSION_CODES.HONEYCOMB;3338 final boolean targetPreIcs = targetSdk < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;3339 final boolean targetPreL = targetSdk < android.os.Build.VERSION_CODES.LOLLIPOP;3340 final boolean targetHcNeedsOptions = context.getResources().getBoolean(3341 R.bool.target_honeycomb_needs_options_menu);3342 final boolean noActionBar = !hasFeature(FEATURE_ACTION_BAR) || hasFeature(FEATURE_NO_TITLE);33433344 if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {3345 addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);3346 } else {3347 clearFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);3348 }
明显看出来,是需要满足某些条件这个menu按钮才会显示出来的。比如targetsdk等,当然也可以通过反射直接调用这个显示menu按键的方法来实现这个功能。这个也是网上一大堆资料告诉我们的解决办法。
try {getWindow().addFlags(WindowManager.LayoutParams.class.getField("FLAG_NEEDS_MENU_KEY").getInt(null));}catch (NoSuchFieldException e) {// Ignore since this field won't exist in most versions of Android}catch (IllegalAccessException e) {Log.w("lxz", "Could not access FLAG_NEEDS_MENU_KEY in addLegacyOverflowButton()", e);}当然,这个解决了一大部分4.0之后的问题,但是我手机升级到 了5.1.1之后,这个方法失效了。安卓就是个坑。。。。。
然后这个时候又想到去阅读源码,只能每个版本的源码去对比,看这个之间具体发生了什么变化。
发现从5.1.0版本之后。这块的源代码变成了这样
3451 final Context context = getContext();3452 final int targetSdk = context.getApplicationInfo().targetSdkVersion;3453 final boolean targetPreHoneycomb = targetSdk < android.os.Build.VERSION_CODES.HONEYCOMB;3454 final boolean targetPreIcs = targetSdk < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;3455 final boolean targetPreL = targetSdk < android.os.Build.VERSION_CODES.LOLLIPOP;3456 final boolean targetHcNeedsOptions = context.getResources().getBoolean(3457 R.bool.target_honeycomb_needs_options_menu);3458 final boolean noActionBar = !hasFeature(FEATURE_ACTION_BAR) || hasFeature(FEATURE_NO_TITLE);34593460 if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {3461 setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE);3462 } else {3463 setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE);3464 }
看这个对比一下,我了个去,谷歌这么干是有道理的。本来一个方法能干到的事情,不需要两个方法,只需要一个方法不同的两个参数就ok,也是谷歌在规范代码吧~
但是苦了我们这些码农。。。。
然后后面其实就简单了,只需要仿照那个反射来找方法来实现这个功能就ok了。
Method m = Window.class.getDeclaredMethod("setNeedsMenuKey", int.class);m.setAccessible(true);m.invoke(getWindow(), new Object[]{WindowManager.LayoutParams.class.getField("NEEDS_MENU_SET_TRUE").getInt(null)});
注意一点这里需要调用的反射是
getDeclaredMethod();// 而不是 <span style="font-family: Arial, Helvetica, sans-serif;">getMethod();</span>
getMethod();
Returns a <code>Method</code> object which represents the public method with the specified name and parameter types. <code>(Class[]) null</code> is equivalent to the empty array. This method first searches the class C represented by this <code>Class</code>, then the superclasses of C and finally the interfaces implemented by C and finally the superclasses of C for a method with matching name.
<pre code_snippet_id="1566952" snippet_file_name="blog_20160127_2_9556582" name="code" class="java">getDeclaredMethod()
Returns a <code>Method</code> object which represents the method matching the specified name and parameter types that is declared by the class represented by this <code>Class</code>.
当然完整代码可能就需要加上一个版本判断来做不同的处理了。
通过这个Build.VERSION.SDK_INT来判断是否满足条件,去反射不同的方法来实现。
Build.VERSION.SDK_INT 21 android 5.0.1
Build.VERSION.SDK_INT 22 android 5.1.1
这觉B是坑爹。。。。
我只能再通过下载下来的源码再跟进去查一次了
发现这个是从sdk 22开始才有的特性
故此具体代码就变成了
if (Build.VERSION.SDK_INT < 22) {getWindow().addFlags(WindowManager.LayoutParams.class.getField("FLAG_NEEDS_MENU_KEY").getInt(null));} else {Method m = Window.class.getDeclaredMethod("setNeedsMenuKey",int.class);m.setAccessible(true);m.invoke(getWindow(),new Object[] { WindowManager.LayoutParams.class.getField("NEEDS_MENU_SET_TRUE").getInt(null) });}
具体的try catch 直接用ide处理下就ok了。
- 怎么让android系统中隐藏的menu按钮显示出来
- Android中menu的显示与隐藏
- 怎么让文件的内容在textArea中显示出来?
- Android的Menu显示不出来
- android中如何让listview的内容全部显示出来
- 怎么让Android4.0以上机器的虚拟按键中显示menu键
- 怎么让Android4.0以上机器的虚拟按键中显示menu键
- 怎么让Android4.0以上机器的虚拟按键中显示menu键
- 怎么让Android4.0以上机器的虚拟按键中显示menu键
- 让u盘的隐藏文件快速显示出来
- Tkinter隐藏窗口再让他显示出来的例子
- 怎么让一个html文件在另一个html文件中适当的位置直接显示出来
- Myeclipse中左边的项目目录调没了,怎么再让它显示出来
- Myeclipse中左边的项目目录调没了,怎么再让它显示出来
- Android 在Fragment或activity中显示与隐藏Menu的菜单
- MFC中按钮的隐藏和显示
- 当menu显示不出来的时候
- 如何将Excel中隐藏的列显示出来
- MP4v2获得h264数据
- mysql中优化sql语句查询的30种方法
- 解锁Oracle账户及修改密码
- 设计模式之Proxy(代理):模拟JDK的动态代理
- Maven
- 怎么让android系统中隐藏的menu按钮显示出来
- 初识Alljoyn
- Dijkstra(迪杰斯特拉)算法和Floyd算法 @as_
- PHP扩展redis使用手册
- 设计模式之:原型模式(Prototype)
- SuperMap超图——点位标注和callout
- 在eclipse中查看sources源码和JavaDoc帮助文档
- 性能测试的概念及其分类
- windows安装composer