在Android4.0以上设备的虚拟按键中显示menu键

来源:互联网 发布:庇古的福利经济学知乎 编辑:程序博客网 时间:2024/06/05 19:56

在 Android4.0以后,google添加了虚拟导航键来替换实体键,到现在Android7.0了基本上导航键上已经没有菜单键了,再查看下网上各种资料之后,研究了下源码,发现是否显示菜单键实在 Window初始化的布局中判断的,也即PhoneWindow的generateLayout函数

在Android 5.1 以下该函数部分代码是这样实现的:

        final Context context = getContext();        final int targetSdk = context.getApplicationInfo().targetSdkVersion;        final boolean targetPreHoneycomb = targetSdk < android.os.Build.VERSION_CODES.HONEYCOMB;        final boolean targetPreIcs = targetSdk < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;        final boolean targetHcNeedsOptions = context.getResources().getBoolean(                com.android.internal.R.bool.target_honeycomb_needs_options_menu);        final boolean noActionBar = !hasFeature(FEATURE_ACTION_BAR) || hasFeature(FEATURE_NO_TITLE);        if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {            addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);        } else {            clearFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);        }

但是再看Android 6.0 的源码,PhoneWindow的generateLayout函数却稍微改变了点:

        final Context context = getContext();        final int targetSdk = context.getApplicationInfo().targetSdkVersion;        final boolean targetPreHoneycomb = targetSdk < android.os.Build.VERSION_CODES.HONEYCOMB;        final boolean targetPreIcs = targetSdk < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;        final boolean targetPreL = targetSdk < android.os.Build.VERSION_CODES.LOLLIPOP;        final boolean targetHcNeedsOptions = context.getResources().getBoolean(                R.bool.target_honeycomb_needs_options_menu);        final boolean noActionBar = !hasFeature(FEATURE_ACTION_BAR) || hasFeature(FEATURE_NO_TITLE);        if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {            setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE);        } else {            setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE);        }

而Android5.1.1的generateLayout函数的那部分代码跟6.0基本上是一样的,所以暂时只看Android 6.0的代码。

在Android6.0的Window类中多了一个方法,setNeedMenuKey 函数,该函数的作用就是设置是否显示虚拟菜单键,在Android5.1.1之前是否显示菜单键是WindowManager.LayoutParams 中的一个flags,而在Android5.1.1及以后,google把这个标记为改到了WindowManager.LayoutParams类中的needsMenuKey 字段去了,可以通过setNeedMenuKey 方法来修改。

说了这么多,也大概明白了怎么回事了,下面就给出一个通用的解决方法,利用反射来完成:

      private void setNeedsMenuKey() {        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {            return;        }        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {            try {                int flags = WindowManager.LayoutParams.class.getField("FLAG_NEEDS_MENU_KEY").getInt(null);                getWindow().addFlags(flags);            } catch (IllegalAccessException e) {                e.printStackTrace();            } catch (NoSuchFieldException e) {                e.printStackTrace();            }        } else {            try {                Method setNeedsMenuKey = Window.class.getDeclaredMethod("setNeedsMenuKey", int.class);                setNeedsMenuKey.setAccessible(true);                int value = WindowManager.LayoutParams.class.getField("NEEDS_MENU_SET_TRUE").getInt(null);                setNeedsMenuKey.invoke(getWindow(), value);            } catch (NoSuchMethodException e) {                e.printStackTrace();            } catch (NoSuchFieldException e) {                e.printStackTrace();            } catch (IllegalAccessException e) {                e.printStackTrace();            } catch (InvocationTargetException e) {                e.printStackTrace();            }        }     }

该函数就可以强行设置在虚拟导航栏中显示菜单按钮,调用位置的话,我是放在setContentView函数之后使用的,亲测有效:

setContentView(R.layout.activity_main);setNeedsMenuKey();

以上就是所有的内容,如有不对的地方,欢迎各位Android开发的小伙伴们一起研究讨论。

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 京东登录名忘了怎么办? 京东已经发货了怎么办 苹果7p黑亮掉漆怎么办 淘宝卖家不肯退运费怎么办 健身付款收据丢了怎么办 收据丢了怎么办能退款 苹果售后不承认基带问题怎么办 电话卡欠费了不用了怎么办 软件移不到sd卡怎么办 手机显示sd卡受损怎么办 美的冰箱出现e6怎么办 美的冰箱显示e6怎么办 冰箱电脑板坏了怎么办 笔记本网线接口坏了怎么办 蓝p吃了一片 怎么办 sd卡上锁了忘记密码怎么办 手机sd卡被锁定怎么办 冰箱制冷管堵了怎么办 冰箱的管子破了怎么办 淘宝京东e卡冻结怎么办 苏宁任性付冻结怎么办 苏宁订单删除了怎么办 联通销户话费有余额怎么办 暖气改地热不热怎么办 老楼房暖气不热怎么办 4s店修不好车怎么办 苏宁的发票丢了怎么办 京东退货没有发票怎么办 发票发错了邮箱怎么办 苹果手机忘记电子邮箱验证码怎么办 退差价把红包退还了怎么办 网上购票票丢了怎么办 岗位人手不够老板又不招人来怎么办 辞职后提成不发怎么办 老板给客户吵架员工该怎么办 冰柜声音大怎么办嗡嗡响 交了钱电没有怎么办 小白熊电动吸奶器显示F1怎么办 花洒的水变小了怎么办 手机插卡处坏了怎么办 吉利帝豪一键启动钥匙没电怎么办