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

 

[java] view plaincopy
  1. package com.silenceburn;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5.   
  6. public class MenuShortCutTester extends Activity {  
  7.     /** Called when the activity is first created. */  
  8.     @Override  
  9.     public void onCreate(Bundle savedInstanceState) {  
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.main);  
  12.           
  13.         setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);  
  14.     }  
  15. }  

 

 

 

为默认的main.xml中的TextView增加一个id属性,之后我们会用菜单选项控制这行字的颜色

 

[xhtml] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     >  
  7. <TextView   
  8.     android:id="@+id/myText"   
  9.     android:layout_width="fill_parent"   
  10.     android:layout_height="wrap_content"   
  11.     android:text="@string/hello"  
  12.     />  
  13. </LinearLayout>  

 

 

 

使用findViewById获取上一步中定义了id的文本对象,将其引用保存在成员变量b中。

重写onPrepareOptionsMenu方法,增加我们自己的菜单项,并注册快捷键,同时增加菜单点击的响应事件。

 

[java] view plaincopy
  1. package com.silenceburn;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.view.Menu;  
  6. import android.view.MenuItem;  
  7. import android.view.MenuItem.OnMenuItemClickListener;  
  8. import android.widget.TextView;  
  9.   
  10. public class MenuShortCutTester extends Activity {  
  11.     /** Called when the activity is first created. */  
  12.     TextView b;  
  13.       
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.main);  
  18.           
  19.         b = (TextView) this.findViewById(R.id.myText);  
  20.           
  21.         setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);  
  22.     }  
  23.       
  24.     @Override  
  25.     public boolean onPrepareOptionsMenu(Menu menu) {  
  26.         // TODO Auto-generated method stub  
  27.         super.onPrepareOptionsMenu(menu);  
  28.           
  29.         menu.removeItem(0);  
  30.         menu.removeItem(1);  
  31.         menu.add( 0, 0, 0, "One").setShortcut('0', '0').setOnMenuItemClickListener(new OnMenuItemClickListener(){  
  32.   
  33.             @Override  
  34.             public boolean onMenuItemClick(MenuItem item) {  
  35.                 // TODO Auto-generated method stub  
  36.                 b.setBackgroundColor(android.graphics.Color.RED);  
  37.                 return true;  
  38.             }});  
  39.         menu.add( 0, 1, 0, "Two").setShortcut('1', '1').setOnMenuItemClickListener(new OnMenuItemClickListener(){  
  40.   
  41.             @Override  
  42.             public boolean onMenuItemClick(MenuItem item) {  
  43.                 // TODO Auto-generated method stub  
  44.                 b.setBackgroundColor(android.graphics.Color.GREEN);  
  45.                 return true;  
  46.             }});   
  47.           
  48.         return true;  
  49.     }  
  50. }  

 

 

 

注意我们一共注册了两个菜单项,

一个叫“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中可以找到如下代码片段:

 

 

[java] view plaincopy
  1. if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) {  
  2.     return false;  
  3. } else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) {  
  4.     if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,   
  5.             keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE)) {  
  6.         return true;  
  7.     }  
  8.     return false;  
  9. }  

 

 

由此可知,当系统检测到 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中我们可以看到如下代码片段:

 

[java] view plaincopy
  1. // Only try to perform menu shortcuts if preparePanel returned true (possible false  
  2. // return value from application not wanting to show the menu).  
  3. if ((st.isPrepared || preparePanel(st, event)) && st.menu != null) {  
  4.     // The menu is prepared now, perform the shortcut on it  
  5.     handled = st.menu.performShortcut(keyCode, event, flags);  
  6. }  

 

 

终于看到menu字样了,这里我们可以看到 if 里面描述的调用条件,

首先当前panel必须已经准备好了(你可以用 onPreparePanel 截获到准备请求),

其次,当前panel必须是有Menu的!(st.menu != null),

从这里我们可以明白DEFAULT_KEYS_SHORTCUT对于没有menu的应用是没有任何效果的。

而且在另一处代码我们会看到还要进行 isShortCut 的判断,所以对于没有快捷键的菜单也是没有任何效果的。

 

那么我们再看看 preparePanel 里面是如何实现的,在其实现中可以找到如下代码片段:

 

[java] view plaincopy
  1. // Callback and return if the callback does not want to show the menu  
  2. if (!cb.onPreparePanel(st.featureId, st.createdPanelView, st.menu)) {  
  3.     return false;  
  4. }  

 

 

至此,就完全明白了!代码在这里回调了 onPreparePanel ,而 onPreparePanel  中会回调  onPrepareOptionsMenu ,

而onPrepareOptionsMenu ,就是我们自己写实现自定义菜单的地方了。

 

为了验证上述推导,我们在onPrepareOptionsMenu 中放入断点,然后在菜单关闭的情况下,输入快捷键,

运行到断点后查看调用堆栈,入下图所示:

 

 

 

堆栈调用顺序可以很清楚的看出我们的推导过程是正确的。至此 DEFAULT_KEYS_SHORTCUT 的实现分析完毕。

 

Android中的常量 DEFAULT_KEYS_SHORTCUT相关推荐

  1. android自定义常量,Android中最佳常量定义方法

    一.常量定义最佳方法 采用左移和与运算,具体参考谷歌常量定义方法. 例子: 现在有一个手机视屏app,有一下标记属性: 1.视屏是否免费 2.是否是视频播放期 3.视频是否为VIP视频 4.视频是否为 ...

  2. android封装好的Color类中的常量

    通过android封装好的Color类中的常量 public static final int BLACK = 0xFF000000; public static final int DKGRAY = ...

  3. android手机 scala环境,在Android中使用Scala中的Java常量

    我在Android上的Scala中开发了一个奇怪的问题.我正在使用sbt android插件,现在我正在尝试让内容提供商工作,但是...在Android中使用Scala中的Java常量 刚刚用Scal ...

  4. Android中如何优雅的定义常量

    本篇博客是笔者的第一篇博客,其实很早之前就有了写博客的想法.但是奈何万事开头难,一直没有下定决心.随着自己积累的知识不断增多,如果不进行总结,不进行思考归纳,有些知识会经常遗忘.对于某些难题,可能当时 ...

  5. 【转】Android菜单详解——理解android中的Menu--不错

    原文网址:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html 前言 今天看了pro android 3中menu这一章,对A ...

  6. Android中WIFI开发总结(一)

    WIFI就是一种无线联网技术,常见的是使用无线路由器.那么在这个无线路由器的信号覆盖的范围内都可以采用WIFI连接的方式进行联网.如果无线路由器连接了一个ADSL线路或其他的联网线路,则又被称为&qu ...

  7. Android中XML的命名空间、自定义属性

    命名空间(namespace) XML 命名空间提供避免元素命名冲突的方法. 举个例子,A学校有名学生叫做林小明,B学校也有名学生叫林小明,那我们如何识别这两名拥有相同名字的同学呢?这时候命名空间就派 ...

  8. [转]Android中程序与Service交互的方式——交互方式

    本文转自:http://blog.csdn.net/yihongyuelan/article/details/7216188 上一篇文章:Android中程序与Service交互的方式--综述 简述了 ...

  9. Android 中ContentProvider和Uri详解

    一.使用ContentProvider(内容提供者)共享数据 ContentProvider在android中的作用是对外共享数据,也就是说你可以通过ContentProvider把应用中的数据共享给 ...

最新文章

  1. html 自动弹出框
  2. 虚幻UE4常见问题最全集合
  3. 工作222:title写活
  4. Java千百问_04异常处理(007)_常见的java异常有哪些(非运行时)
  5. 无法从服务器获得响应,什么是java.io.EOFException的,消息:无法从服务器读取响应。 预期读4个字节,...
  6. 【codevs1040】【01NOIPTG】统计单词个数,字符串的划分DP
  7. UVA571 - Jugs(数论)
  8. 背景半透明(HTML、CSS)
  9. 全网最详细的VMware虚拟机下载安装教程
  10. 使用vue+HBulider云游戏接口开发单击斗地主网页版
  11. cefsharp修改html,CefSharp v62修改方法(支持.net4.0)
  12. speak 计算机英语作文,【必备】英语作文5篇
  13. GIS数据在哪里下载
  14. ip地址分类和子网掩码
  15. 深度学习: 细粒度图像分类 (fine-grained image recognition)
  16. TextToSpeech文字转语音
  17. 世界上最好的图片无损压缩软件
  18. centos7 team 绑定
  19. Recurrent Neural Networks 循环神经网络
  20. SimpleDateFormat日期格式化顺延,setLenient关闭顺延

热门文章

  1. tomcat和nginx的使用
  2. 常用Linux基础命令
  3. 百个JavaScript函数以及基础写法汇总
  4. .net中存储过程的应用
  5. 简单的实现购物车功能,还有不到位的地方,加油!!!
  6. node使用npm一句命令停止某个端口号 xl_close_port
  7. 介绍27款经典的CSS框架
  8. CIO黄嘉粤谈互联网金融与CIO发展
  9. 博为峰Java技术题 ——JavaEE Servlet 国际化Ⅲ
  10. vsftpd设置虚拟用户