Android中的常量 DEFAULT_KEYS_SHORTCUT
1. 关于 DEFAULT_KEYS_SHORTCUT 的 API文档介绍
Use with setDefaultKeyMode(int) to execute a menu shortcut in default key handling.
That is, the user does not need to hold down the menu key to execute menu shortcuts.
从字面上看,其含义是指,将默认的按键输入作为菜单快捷键进行处理。
也就是说,用户不需要按下menu按键,就可以处理菜单快捷键,听起来非常神奇,究竟是不是这样呢?
2.编写示例程序
我们编写一个程序验证一下其功能,首先新建一个工程,并设置默认按键模式为 DEFAULT_KEYS_SHORTCUT
- package com.silenceburn;
- import android.app.Activity;
- import android.os.Bundle;
- public class MenuShortCutTester extends Activity {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
- }
- }
为默认的main.xml中的TextView增加一个id属性,之后我们会用菜单选项控制这行字的颜色
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <TextView
- android:id="@+id/myText"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="@string/hello"
- />
- </LinearLayout>
使用findViewById获取上一步中定义了id的文本对象,将其引用保存在成员变量b中。
重写onPrepareOptionsMenu方法,增加我们自己的菜单项,并注册快捷键,同时增加菜单点击的响应事件。
- package com.silenceburn;
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.Menu;
- import android.view.MenuItem;
- import android.view.MenuItem.OnMenuItemClickListener;
- import android.widget.TextView;
- public class MenuShortCutTester extends Activity {
- /** Called when the activity is first created. */
- TextView b;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- b = (TextView) this.findViewById(R.id.myText);
- setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
- }
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- // TODO Auto-generated method stub
- super.onPrepareOptionsMenu(menu);
- menu.removeItem(0);
- menu.removeItem(1);
- menu.add( 0, 0, 0, "One").setShortcut('0', '0').setOnMenuItemClickListener(new OnMenuItemClickListener(){
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- // TODO Auto-generated method stub
- b.setBackgroundColor(android.graphics.Color.RED);
- return true;
- }});
- menu.add( 0, 1, 0, "Two").setShortcut('1', '1').setOnMenuItemClickListener(new OnMenuItemClickListener(){
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- // TODO Auto-generated method stub
- b.setBackgroundColor(android.graphics.Color.GREEN);
- return true;
- }});
- return true;
- }
- }
注意我们一共注册了两个菜单项,
一个叫“One”,点击时将文本对象 b 的背景颜色改为红色,同时定义其快捷键为0
一个叫“Two”,点击时将文本对象 b 的背景颜色改为绿色,同时定义其快捷键为1
至此示例程序完成。
3.验证使用示例程序
启动AVD,运行上述程序,程序启动后,我们应当看到是黑底灰字,点击menu按钮,可以看到One和Two两个菜单选项。
如下图所示:
目前Menu是打开状态,
点击One ,将把“helloworld...”字样的背景色变为红色,
点击Two ,将把“helloworld...”字样的背景色变为红绿色。
或者我们点设置好的快捷键 0 和 1,发现可以直接调用菜单选项控制颜色变化。
到目前为止一切都很正常,不过,神奇的现在来了!
我们首先关闭菜单,
然后直接点键盘键"0“,看看会发生什么。再直接点键盘键"1" ,看看会发生什么。
哈哈,在没有激活菜单的情况下,菜单项快捷键被直接调用了!根本不需要打开菜单,就可以用激活菜单快捷键!
什么?有位同学说快捷键就应该是这样子把,那好,请你把 onCreate 里面的
setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT); 改为 setDefaultKeyMode(DEFAULT_KEYS_DISABLE);
然后再运行试试,在不打开菜单的情况下,你就是把 0 和 1 按坏,系统也不会理你的呵呵
4.浅析实现原理
那么这神奇的功能是如何实现的呢?我们试着通过分析android源码找到答案。
首先顺藤摸瓜,我们找一找系统是如何处理 DEFAULT_KEYS_SHORTCUT 关键字的,
在Activity.java中可以找到如下代码片段:
- if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) {
- return false;
- } else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) {
- if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,
- keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE)) {
- return true;
- }
- return false;
- }
由此可知,当系统检测到 DEFAULT_KEYS_SHORTCUT 关键字时,实际调用了
getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,
keyCode, event,Menu.FLAG_ALWAYS_PERFORM_CLOSE)
我们继续追寻,但是这里会遇到一个困难,就是查阅API文档你会发现,performPanelShortcut函数是个纯虚函数!
接下来该怎么办呢?既然功能顺利执行了,那么这个纯虚函数一定会有一个实现的。这个实现类必然是window类的子类。
所以我们在OnCreate里面加上一行代码 Window w = this.getWindow();
然后通过Eclipse的调试器,利用RTTI查看其实现类,结果如下图:
可以看的很清楚,实现类是 PhoneWindow ,
这样我们就可以到 PhoneWindow 的源码中去查找performPanelShortcut的实现了。
在PhoneWindow.java中我们可以看到如下代码片段:
- // Only try to perform menu shortcuts if preparePanel returned true (possible false
- // return value from application not wanting to show the menu).
- if ((st.isPrepared || preparePanel(st, event)) && st.menu != null) {
- // The menu is prepared now, perform the shortcut on it
- handled = st.menu.performShortcut(keyCode, event, flags);
- }
终于看到menu字样了,这里我们可以看到 if 里面描述的调用条件,
首先当前panel必须已经准备好了(你可以用 onPreparePanel 截获到准备请求),
其次,当前panel必须是有Menu的!(st.menu != null),
从这里我们可以明白DEFAULT_KEYS_SHORTCUT对于没有menu的应用是没有任何效果的。
而且在另一处代码我们会看到还要进行 isShortCut 的判断,所以对于没有快捷键的菜单也是没有任何效果的。
那么我们再看看 preparePanel 里面是如何实现的,在其实现中可以找到如下代码片段:
- // Callback and return if the callback does not want to show the menu
- if (!cb.onPreparePanel(st.featureId, st.createdPanelView, st.menu)) {
- return false;
- }
至此,就完全明白了!代码在这里回调了 onPreparePanel ,而 onPreparePanel 中会回调 onPrepareOptionsMenu ,
而onPrepareOptionsMenu ,就是我们自己写实现自定义菜单的地方了。
为了验证上述推导,我们在onPrepareOptionsMenu 中放入断点,然后在菜单关闭的情况下,输入快捷键,
运行到断点后查看调用堆栈,入下图所示:
堆栈调用顺序可以很清楚的看出我们的推导过程是正确的。至此 DEFAULT_KEYS_SHORTCUT 的实现分析完毕。
Android中的常量 DEFAULT_KEYS_SHORTCUT相关推荐
- android自定义常量,Android中最佳常量定义方法
一.常量定义最佳方法 采用左移和与运算,具体参考谷歌常量定义方法. 例子: 现在有一个手机视屏app,有一下标记属性: 1.视屏是否免费 2.是否是视频播放期 3.视频是否为VIP视频 4.视频是否为 ...
- android封装好的Color类中的常量
通过android封装好的Color类中的常量 public static final int BLACK = 0xFF000000; public static final int DKGRAY = ...
- android手机 scala环境,在Android中使用Scala中的Java常量
我在Android上的Scala中开发了一个奇怪的问题.我正在使用sbt android插件,现在我正在尝试让内容提供商工作,但是...在Android中使用Scala中的Java常量 刚刚用Scal ...
- Android中如何优雅的定义常量
本篇博客是笔者的第一篇博客,其实很早之前就有了写博客的想法.但是奈何万事开头难,一直没有下定决心.随着自己积累的知识不断增多,如果不进行总结,不进行思考归纳,有些知识会经常遗忘.对于某些难题,可能当时 ...
- 【转】Android菜单详解——理解android中的Menu--不错
原文网址:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html 前言 今天看了pro android 3中menu这一章,对A ...
- Android中WIFI开发总结(一)
WIFI就是一种无线联网技术,常见的是使用无线路由器.那么在这个无线路由器的信号覆盖的范围内都可以采用WIFI连接的方式进行联网.如果无线路由器连接了一个ADSL线路或其他的联网线路,则又被称为&qu ...
- Android中XML的命名空间、自定义属性
命名空间(namespace) XML 命名空间提供避免元素命名冲突的方法. 举个例子,A学校有名学生叫做林小明,B学校也有名学生叫林小明,那我们如何识别这两名拥有相同名字的同学呢?这时候命名空间就派 ...
- [转]Android中程序与Service交互的方式——交互方式
本文转自:http://blog.csdn.net/yihongyuelan/article/details/7216188 上一篇文章:Android中程序与Service交互的方式--综述 简述了 ...
- Android 中ContentProvider和Uri详解
一.使用ContentProvider(内容提供者)共享数据 ContentProvider在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给 ...
最新文章
- html 自动弹出框
- 虚幻UE4常见问题最全集合
- 工作222:title写活
- Java千百问_04异常处理(007)_常见的java异常有哪些(非运行时)
- 无法从服务器获得响应,什么是java.io.EOFException的,消息:无法从服务器读取响应。 预期读4个字节,...
- 【codevs1040】【01NOIPTG】统计单词个数,字符串的划分DP
- UVA571 - Jugs(数论)
- 背景半透明(HTML、CSS)
- 全网最详细的VMware虚拟机下载安装教程
- 使用vue+HBulider云游戏接口开发单击斗地主网页版
- cefsharp修改html,CefSharp v62修改方法(支持.net4.0)
- speak 计算机英语作文,【必备】英语作文5篇
- GIS数据在哪里下载
- ip地址分类和子网掩码
- 深度学习: 细粒度图像分类 (fine-grained image recognition)
- TextToSpeech文字转语音
- 世界上最好的图片无损压缩软件
- centos7 team 绑定
- Recurrent Neural Networks 循环神经网络
- SimpleDateFormat日期格式化顺延,setLenient关闭顺延