菜单实现Android中的常量 DEFAULT_KEYS_SHORTCUT

文章结束给大家来个程序员笑话:[M]

    

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( 000"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( 010"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 的实现析分毕完。

    

 

    


文章结束给大家分享下程序员的一些笑话语录: 神灯新篇
一个程序员在海滩上发现了一盏神灯。他在灯上擦了几下,一个妖怪就从灯里跳出来说:“我是世界上法术最强的妖怪。我可以实现你的任何梦想,但现在,我只能满足你一个愿望。”程序员摊开了一幅中东地图说:“我想让中东得到永久的和平。”妖怪答道:“哦,我没办法。自打创世纪以来,那里的战火就没有停息过。这世上几乎没有我办不到的事,但这件事除外。”程序员于是说:“好吧,我是一个程序员,为许多用户编写过程序。你能让他们把需求表述得更清楚些,并且让我们的软件项目有那么一两次按进度按成本完成吗?”妖怪说:“唔,我们还是来看中东地图吧。”

posted @ 2013-05-09 20:38  xinyuyuanm  阅读(443)  评论(0编辑  收藏  举报