在android的状态栏(statusbar)中增加menu,home和back快捷键的方法

在状态栏上添加Menu,Back,Home三个按钮的方法,在下文有良好的阐述。详见:

《在android的状态栏(statusbar)中增加menu,home和back快捷键的方法》http://blog.csdn.net/freshui/archive/2010/07/15/5738115.aspx

在使用过程中,存在两个问题:

  • HOME键在我的机器上无效
  • 连击按钮时,由于有时Intent未响应,导致弹起操作未响应直接诶被WindowsManager抛掉。这样就出现了虽然手已离开屏幕,但按钮出现高亮的状态。

1、对于第一个问题,我的方法是把home键单独进行处理,向launcher发送一个启动activity的Intent,这样可以直接回到桌面上。在原方法的基础上,对Home单独进行处理。

1   if     (RESV_KEY_HOME     =  =     mResvKeyCode)    
2   {    
3               Log  .  d(TAG,     " HOME   button   Intent! "  );    
4               Intent     intent  =     new     Intent(Intent  .  ACTION_MAIN);    
5               intent  .  setFlags(Intent  .  FLAG_ACTIVITY_NEW_TASK);    
6               intent  .  addCategory(Intent  .  CATEGORY_HOME);    
7               mService  .  sendIntent2(intent);    
8      }    
9   else    
10  {    
11              Log  .  d(TAG,     " other   two   buttons   Intent! "  );    
12              Intent     intent     =     new     Intent(Intent  .  ACTION_ICONKEY_CHANGED);    
13              intent  .  addFlags(Intent  .  FLAG_RECEIVER_REGISTERED_ONLY);    
14              intent  .  putExtra(  " keycode "  ,           mResvKeyCode);    
15              mService  .  sendIntent(intent);    
16  } 

在StatusBarService.java中添加sendIntent2方法

void     sendIntent2(Intent     intent)    
{    
            mContext  .  startActivity(intent);    
} 

2、第二个问题的修正思想是使用Animation逐帧动画来使得按钮从完成 正常态按下后-变化至高亮态-恢复正常态 这一周期。

a. 先在res/layout(与status_bar.xml同目录)中添加三个animation动画xml配置文件。

分别是

animation_home.xml:

1   <  ?xml  version  =  "  1.0  "  encoding  =  "  utf-8  "  ?  >    
2   <  animation-list  xmlns:android  =  "  http://schemas.android.com/apk/res/android  " 
3            android:oneshot  =  "  true  "  >    
4               <  item    
5                        android:duration  =  "  80  "    
6                        android:drawable  =  "  @drawable/stat_home  "     >    
7               <  /item  >    
8               <  item    
9                        android:duration  =  "  80  "    
10                       android:drawable  =  "  @drawable/stat_home_pressed  "     >    
11              <  /item  >    
12              <  item    
13                       android:duration  =  "  80  "    
14                       android:drawable  =  "  @drawable/stat_home  "     >    
15              <  /item  >    
16  <  /animation-list  > 

animation_back.xml:

1   <  ?xml  version  =  "  1.0  "  encoding  =  "  utf-8  "  ?  >    
2   <  animation-list  xmlns:android  =  "  http://schemas.android.com/apk/res/android  " 
3            android:oneshot  =  "  true  "  >    
4               <  item    
5                        android:duration  =  "  80  "    
6                        android:drawable  =  "  @drawable/stat_back  "     >    
7               <  /item  >    
8               <  item    
9                        android:duration  =  "  80  "    
10                       android:drawable  =  "  @drawable/stat_back_pressed  "     >    
11              <  /item  >    
12              <  item    
13                       android:duration  =  "  80  "    
14                       android:drawable  =  "  @drawable/stat_back  "     >    
15              <  /item  >    
16  <  /animation-list  > 
17 
18    
19 

animation_menu.xml:

1   <  ?xml  version  =  "  1.0  "  encoding  =  "  utf-8  "  ?  >    
2   <  animation-list  xmlns:android  =  "  http://schemas.android.com/apk/res/android  " 
3            android:oneshot  =  "  true  "  >    
4               <  item    
5                        android:duration  =  "  80  "    
6                        android:drawable  =  "  @drawable/stat_menu  "     >    
7               <  /item  >    
8               <  item    
9                        android:duration  =  "  80  "    
10                       android:drawable  =  "  @drawable/stat_menu_pressed  "     >    
11              <  /item  >    
12              <  item    
13                       android:duration  =  "  80  "    
14                       android:drawable  =  "  @drawable/stat_menu  "     >    
15              <  /item  >    
16  <  /animation-list  > 
17 
18 

这三个xml文件分别对应着 home back menu的动画过程

b . 在res/layout/status_bar.xml中修改Imageview的background指向上述三个xml配置文件:

1    <  ?xml  version  =  "  1.0  "  encoding  =  "  utf-8  "  ?  >    
2    <!--              android:background="@drawable/status_bar_closed_default_background"     -->    
3    <  com.android.server.status.StatusBarView  xmlns:android  =  " http://schemas.android.com/apk/res/android  "    
4             android:background  =  "  @drawable/statusbar_background  "    
5             android:orientation  =  "  vertical  "    
6             android:focusable  =  "  true  "    
7             android:descendantFocusability  =  "  afterDescendants  "    
8                >    
9   
10               <  LinearLayout  android:id  =  "  @+id/icons  "    
11                        android:layout  _width=  "  fill_parent  "    
12                        android:layout  _height=  "  fill_parent  "    
13                        android:orientation  =  "  horizontal  "  >    
14                              <!--  Ethan.zhao     :     Start     Add     home     button     on     status_bar  -->            
15                                                <  ImageView    
16                                                android:id  =  "  @+id/status_home  "    
17                                                   android:layout  _width=  "  wrap_content  "       
18                                                   android:layout  _height=  "  wrap_content  "       
19                                                   android:layout  _gravity=  "  top  "    
20                                                   android:background  =  "  @layout/animation_home  "    
21                                       /  >    
22                              <!--  Ethan.zhao     :     Start     Add     home     button     on     status_bar  -->                        
23  
24                           <  com.android.server.status.IconMerger  android:id  =  "  @+id/notificationIcons  "   
25                                    android:layout  _width=  "  0dip  "    
26                                    android:layout  _weight=  "  1  "    
27                                    android:layout  _height=  "  fill_parent  "    
28                                    android:layout  _alignParentLeft=  "  true  "    
29                                    android:paddingLeft  =  "  6dip  "    
30                                    android:gravity  =  "  center_vertical  "    
31                                    android:orientation  =  "  horizontal  "  /  >       
32  
33                           <  LinearLayout  android:id  =  "  @+id/statusIcons  "    
34                                    android:layout  _width=  "  wrap_content  "    
35                                    android:layout  _height=  "  fill_parent  "    
36                                    android:layout  _alignParentRight=  "  true  "    
37                                    android:paddingRight  =  "  6dip  "    
38                                    android:gravity  =  "  center_vertical  "    
39                                    android:orientation  =  "  horizontal  "  /  >    
40                              <!--  Ethan.zhao     :     Start     Add     menu/back     button     on     status_bar  -->   
41                                       <  ImageView    
42                                                android:id  =  "  @+id/status_menu  "    
43                                                android:layout  _width=  "  wrap_content  "    
44                                                android:layout  _height=  "  wrap_content  "    
45                                                android:layout  _gravity=  "  top  "       
46                                                android:background  =  "  @layout/animation_menu  "    
47                                          /  >    
48  
49                                       <  ImageView    
50                                                android:id  =  "  @+id/status_back  "    
51                                                android:layout  _width=  "  wrap_content  "    
52                                                android:layout  _height=  "  wrap_content  "    
53                                                android:layout  _gravity=  "  top  "       
54                                                android:background  =  "  @layout/animation_back  "    
55                                          /  >    
56                           <!--  Ethan.zhao     :     End     Add     three     button     on     status_bar  -->       
57               <  /LinearLayout  >    
58               <  LinearLayout  android:id  =  "  @+id/ticker  "    
59                        android:layout  _width=  "  fill_parent  "    
60                        android:layout  _height=  "  fill_parent  "    
61                        android:paddingLeft  =  "  6dip  "    
62                        android:animationCache  =  "  false  "    
63                        android:orientation  =  "  horizontal  "     >    
64                           <  ImageSwitcher  android:id  =  "  @+id/tickerIcon  "    
65                                    android:layout  _width=  "  wrap_content  "    
66                                    android:layout  _height=  "  fill_parent  "    
67                                    android:layout  _marginRight=  "  8dip  "    
68                                       >    
69                                       <  com.android.server.status.AnimatedImageView    
70                                                android:layout  _width=  "  25dip  "    
71                                                android:layout  _height=  "  25dip  "    
72                                                   /  >    
73                                       <  com.android.server.status.AnimatedImageView    
74                                                android:layout  _width=  "  25dip  "    
75                                                android:layout  _height=  "  25dip  "    
76                                                   /  >    
77                           <  /ImageSwitcher  >    
78                           <  com.android.server.status.TickerView  android:id  =  "  @+id/tickerText  "    
79                                    android:layout  _width=  "  0dip  "    
80                                    android:layout  _weight=  "  1  "    
81                                    android:layout  _height=  "  wrap_content  "    
82                                    android:paddingTop  =  "  2dip  "    
83                                    android:paddingRight  =  "  10dip  "  >    
84                                       <  TextView    
85                                                android:layout  _width=  "  fill_parent  "    
86                                                android:layout  _height=  "  wrap_content  "    
87                                                android:singleLine  =  "  true  "    
88                                                android:textColor  =  "  #ff000000  "     /  >    
89                                       <  TextView    
90                                                android:layout  _width=  "  fill_parent  "    
91                                                android:layout  _height=  "  wrap_content  "    
92                                                android:singleLine  =  "  true  "    
93                                                android:textColor  =  "  #ff000000  "     /  >    
94                           <  /com.android.server.status.TickerView  >    
95               <  /LinearLayout  >    
96  
97               <  com.android.server.status.DateView  android:id  =  "  @+id/date  "    
98                        android:layout  _width=  "  wrap_content  "    
99                        android:layout  _height=  "  fill_parent  "    
100                       android:singleLine  =  "  true  "    
101                       android:textSize  =  "  16sp  "    
102                       android:textStyle  =  "  bold  "    
103                       android:gravity  =  "  center_vertical|left  "    
104                       android:paddingLeft  =  "  6px  "    
105                       android:paddingRight  =  "  6px  "    
106                       android:textColor  =  "  ?android:attr/textColorPrimaryInverse  "    
107                       android:background  =  "  @drawable/statusbar_background  "    
108                          /  >    
109  <  /com.android.server.status.StatusBarView  > 

c . 修改StatusBarView.java文件,加入Animation相关代码:

添加三个AnimationDrawable:

AnimationDrawable     mHomeAnimation;    
AnimationDrawable     mBackAnimation;    
AnimationDrawable     mMenuAnimation; 

在onFinishInflate()方法中

mHomeAnimation     =     (AnimationDrawable)     mHomeIcon  .  getBackground();    
mBackAnimation     =     (AnimationDrawable)     mBackIcon  .  getBackground();    
mMenuAnimation     =     (AnimationDrawable)     mMenuIcon  .  getBackground(); 

updateResvKeyIcon这个方法,改造成如下这样:

1   private     int     updateResvKeyIcon(  int     key)       
2   {       
3               if  (key     =  =     RESV_KEY_BACK) 
4               {       
5                           mBackAnimation  .  run();    
6               } 
7               else     if  (key     =  =     RESV_KEY_HOME) 
8               {       
9                           mHomeAnimation  .  run();    
10              } 
11              else     if  (key     =  =     RESV_KEY_MENU) 
12              {       
13                          mMenuAnimation  .  run();    
14              }       
15              return     0  ;       
16  }       

d. 注释掉所有的updateResvKeyIcon方法,仅保留以下一个,并加上判断语句。

1  i f(mResvKeyState     =  =     -  1  )     //     remembered     key     state,     no     reserve       
2                {       
3                     switch  (getResvKeyArea(event))  {       
4                                       case     RESV_KEY_HOME  :       
5                                       case     RESV_KEY_BACK  :       
6                                       case     RESV_KEY_MENU  :       
7                                       {       
8                                                mResvKeyState     =     event  .  getAction();       
9                                                mResvKeyCode        =     getResvKeyArea(event);       
10                                                     i  f     (mResvKeyState  =  =  MotionEvent  .  ACTION_DOWN)    updateResvKeyIcon(mResvKeyCode);  //  这句改成这样
 
 
附件下载如下:

http://download.csdn.net/source/2807668





http://blog.csdn.net/freshui/article/details/5738115


需要说明的是:刚入手android没几天,对系统还不算很熟悉,这篇文章是基于前一篇转帖做的。只是觉得他的方法有些麻烦,而且改出来的效果也不是我想要的。

  

由于完全改了status bar,建议先做几张png图片,加到

Frameworks/base/core/res/res/drawable

下。最好做一张背景图,替换 statusbar_background.png

另外我又加了几张icon,分别是home menu和back的正常和按下状态。

这些图片为:

stat_home.png

stat_home_pressed.png

stat_back.png

stat_back_pressed.png

stat_menu.png

stat_menu_pressed.png

 

 

修改步骤为:

 

一.    修改xml界面

 

1. 增加图标

 

当然,更改整个status bar避免不要要对源码大刀修一下。我的该法是:

 修改status bar的layerout文件:

Frameworks/base/core/res/res/layout/status_bar.xml

在原来的linearlayout中新增三个image view

 

  1. <LinearLayout android:id="@+id/icons"  
  2.     android:layout_width="fill_parent"  
  3.     android:layout_height="fill_parent"  
  4.     android:orientation="horizontal">  
  5.   
  6.           <ImageView android:id="@+id/status_home"  
  7.                  android:layout_width="wrap_content"  
  8.                  android:layout_height="wrap_content"  
  9.                  android:layout_gravity="top"  
  10.                  android:paddingTop="6dip"  
  11.                  android:paddingRight="10dip"  
  12.                  android:paddingLeft="10dip"  
  13.                  android:src="@drawable/stat_home" />  
  14.   
  15.     <com.android.server.status.IconMerger android:id="@+id/notificationIcons"  
  16.         android:layout_width="0dip"  
  17.         android:layout_weight="1"  
  18.         android:layout_height="fill_parent"  
  19.         android:layout_alignParentLeft="true"  
  20.         android:paddingLeft="6dip"  
  21.         android:gravity="center_vertical"  
  22.         android:orientation="horizontal"/>    
  23.           
  24.     <LinearLayout android:id="@+id/statusIcons"  
  25.         android:layout_width="wrap_content"  
  26.         android:layout_height="fill_parent"  
  27.         android:layout_alignParentRight="true"  
  28.         android:paddingRight="6dip"  
  29.         android:gravity="center_vertical"  
  30.         android:orientation="horizontal"/>      
  31.   
  32.           <ImageView android:id="@+id/status_menu"  
  33.                  android:layout_width="wrap_content"  
  34.                  android:layout_height="wrap_content"  
  35.                  android:layout_gravity="top"  
  36.                  android:paddingTop="6dip"  
  37.                  android:paddingLeft="10dip"  
  38.                  android:paddingRight="10dip"  
  39.                  android:src="@drawable/stat_menu" />  
  40.   
  41.           <ImageView android:id="@+id/status_back"  
  42.                  android:layout_width="wrap_content"  
  43.                  android:layout_height="wrap_content"  
  44.                  android:layout_gravity="top"  
  45.                  android:paddingTop="6dip"  
  46.                  android:paddingRight="10dip"  
  47.                  android:paddingLeft="10dip"  
  48.                  android:src="@drawable/stat_back" />  
  49.   
  50. /LinearLayout>  
  

这样做的好处就是简单。同时保证最右端是home按钮,最左端是back按钮,不受它本来的约束。这样status bar上即可看到这些按钮了。

       图标的位置,可通过修改 paddingRight, paddingLeft 和paddingTop的值达到最佳视觉效果。

 

2. 修改status bar的高度。

 

既然要在status bar上增加那么几个按钮,当然是想要使用触摸操作的,android自带的status bar高度太小,不适用。对于7寸屏的话,50pixel的高度应该是差不多了。

修改高度很简单,如我转的shinning mm的博文。

修改frameworks/base/core/res/res/values/dimens.xml的status_bar_height属性

    <!-- Height of the status bar -->

    <dimen name="status_bar_height">50dip</dimen>

当然,如果相改title的高度,可以修改 Frameworks/base/core/res/res/values/themes.xml中的Window attributes的windowTitleSize值,不过我觉得没必要,改了反倒不好看了 :)

 

编译运行一下:

 

  1. ~/donut$ source ./env.sh  
  2. ~/donut$ make –j8  
  3. ~/donut$ emulator –skin WVGA800  

, 看状态栏是不是改变了?

 

 

 

二 为按钮添加动态效果

 

添加动态效果,就是触摸按下hilight,松开或者移出后恢复的动作。这一块,我是通过修改frameworks/base/services/java/com/android/server/status/StatusBarView.java实现的。

 

1. 获取statusbar中新增加的icon的handler。

 

在类中新增加三个成员(这需要import android.widget.ImageView;):

 

 

  1. ImageView mHomeIcon;  
  2. ImageView mBackIcon;  
  3. ImageView mMenuIcon;  
      

同时增加三个常量,表示这些icon对应的键值(这需要import android.view.KeyEvent;)

 

  1. public static final int RESV_KEY_HOME = KeyEvent.KEYCODE_HOME;  
  2. public static final int RESV_KEY_BACK = KeyEvent.KEYCODE_BACK;  
  3. public static final int RESV_KEY_MENU = KeyEvent.KEYCODE_MENU;;  
   

在onFinishInflate()中,获得实际的对象:

  1. mHomeIcon = (ImageView)findViewById(R.id.status_home);  
  2. mBackIcon = (ImageView)findViewById(R.id.status_back);  
  3. mMenuIcon = (ImageView)findViewById(R.id.status_menu);  

 

 

这三个对象就是我们在status_bar.xml中添加的。

 

2. 添加触摸处理。

首先,应该判断是那个图标被按下,这个我们在StatusBarView.Java的onTouchEvent中来判断。

这里,我做了一个小的按键状态,已方便处理按下、弹起和移出的动作。

首先增加两个状态成员:

 

  1. int mResvKeyState = -1;  //记住的上次按键状态, -1为无状态。  
  2. int mResvKeyCode  = -1;  //记住的上次按键值,-1为无状态。  
            

 

 

这样我的onTouchEvent就变成这样了:

 

  1. @Override  
  2.    public boolean onTouchEvent(MotionEvent event) {  
  3.     if(mService.mExpanded==true || mService.mTracking==true){  
  4.        if (event.getAction() != MotionEvent.ACTION_DOWN) {  
  5.            mService.interceptTouchEvent(event);  
  6.        }  
  7.         return true;  
  8.     }  
  9.   
  10.     if(mResvKeyState == -1) // remembered key state, no reserve  
  11.     {  
  12.         switch(getResvKeyArea(event)){  
  13.             case RESV_KEY_HOME:  
  14.             case RESV_KEY_BACK:  
  15.             case RESV_KEY_MENU:  
  16.             {  
  17.                 mResvKeyState = event.getAction();  
  18.                 mResvKeyCode  = getResvKeyArea(event);  
  19.   
  20.                 updateResvKeyIcon(mResvKeyState, mResvKeyCode);  
  21.             }  
  22.             break;  
  23.               
  24.             default:  
  25.             if (event.getAction() != MotionEvent.ACTION_DOWN) {  
  26.                 mService.interceptTouchEvent(event);  
  27.             }  
  28.         }  
  29.     }else{  
  30.         mResvKeyState = event.getAction(); // new state  
  31.           
  32.         if(mResvKeyState == MotionEvent.ACTION_MOVE){  
  33.             if(mResvKeyCode != getResvKeyArea(event)){  
  34.                 /* out of bound, resume the icon */  
  35.                 updateResvKeyIcon(MotionEvent.ACTION_UP, mResvKeyCode);  
  36.                   
  37.                 mResvKeyCode  = -1;  
  38.                 mResvKeyState = -1;  
  39.             }  
  40.         }else if(mResvKeyState == MotionEvent.ACTION_UP){  
  41.             updateResvKeyIcon(mResvKeyState, mResvKeyCode);  
  42.             mResvKeyCode  = -1;  
  43.             mResvKeyState = -1;  
  44.         }else{  
  45.             Log.d(TAG, "state machine error! Never be here!");  
  46.         }  
  47.     }  
  48.       
  49.        return true;  
  50.    }  

里面用到的两个private方法简单实现如下:

  1. private int getResvKeyArea(MotionEvent event)  
  2. {  
  3.     if(  (event.getX() <= mHomeIcon.getRight())  
  4.       && (event.getY() <= this.getHeight()) ){  
  5.         return RESV_KEY_HOME;  
  6.     }  
  7.     else if(  (event.getX() >= mBackIcon.getLeft())  
  8.       && (event.getY() <= this.getHeight()) ){  
  9.         return RESV_KEY_BACK;  
  10.     }  
  11.     else if(  (event.getX() >= mMenuIcon.getLeft())  
  12.       && (event.getY() <= this.getHeight()) ){  
  13.         return RESV_KEY_MENU;  
  14.     }else  
  15.         return -1;  
  16. }  
  17.   
  18. private int updateResvKeyIcon(int state, int key)  
  19. {  
  20.     if(key == RESV_KEY_BACK){  
  21.         if(state == MotionEvent.ACTION_UP){  
  22.             mBackIcon.setImageResource(com.android.internal.R.drawable.stat_back);  
  23.         }else if(state == MotionEvent.ACTION_DOWN){  
  24.             mBackIcon.setImageResource(com.android.internal.R.drawable.stat_back_pressed);  
  25.         }  
  26.     }else if(key == RESV_KEY_HOME){  
  27.         if(state == MotionEvent.ACTION_UP){  
  28.             mHomeIcon.setImageResource(com.android.internal.R.drawable.stat_home);  
  29.         }else if(state == MotionEvent.ACTION_DOWN){  
  30.             mHomeIcon.setImageResource(com.android.internal.R.drawable.stat_home_pressed);  
  31.         }  
  32.     }else if(key == RESV_KEY_MENU){  
  33.         if(state == MotionEvent.ACTION_UP){  
  34.             mMenuIcon.setImageResource(com.android.internal.R.drawable.stat_menu);  
  35.         }else if(state == MotionEvent.ACTION_DOWN){  
  36.             mMenuIcon.setImageResource(com.android.internal.R.drawable.stat_menu_pressed);  
  37.         }  
  38.     }  
  39.       
  40.     return 0;  
  41. }  

 

同时,我不想再在按下这些icon的时候,触发下拉动作,我也改了onInterceptTouchEvent函数:

  1.  @Override  
  2.  public boolean onInterceptTouchEvent(MotionEvent event) {  
  3.     if(  (event.getX() > mHomeIcon.getRight())  
  4.  &&  (event.getX() < mMenuIcon.getLeft())){  
  5.         return mService.interceptTouchEvent(event)  
  6.              ? true : super.onInterceptTouchEvent(event);  
  7.     }  
  8.   
  9.     return false;  
  10. }  

 

 

 

 

再编译一下,看一下结果 :) 是不是能动了?

 

 

 

三,添加相应事件

 

1. 添加新的intent

首先是新增一条intent, 在framework/base/core/java/android/content/intent.java中增加

 

 

 

 

  1. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)  
  2. public static final String ACTION_ICONKEY_CHANGED = "android.intent.action.ICONKEY_CHANGED";  
  

 

 

2. 发送intent 

  在StatusBarView.java的OnKeyEvent中,松开按键的分支else if(mResvKeyState == MotionEvent.ACTION_UP)操作中加入发送intent的动作:

  1. Intent intent = new Intent(Intent.ACTION_ICONKEY_CHANGED);  
  2. intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);  
  3. intent.putExtra("keycode",   mResvKeyCode);  
  4. mService.sendIntent(intent);  

这个intent是只有注册的接收者才能接收。

 

这里,我们是通过StatusBarService来发送这个intent的。

在StatusBarService.java中新增一个方法:

  1. void sendIntent(Intent intent)  
  2. {  
  3.     mContext.sendBroadcast(intent);  
  4. }  

 

3.接收并处理intent

这个就要修改StatusBarPolicy.java了

首先,在构造函数中加入Intent的filter,注册号这个intent的receiver。

  filter.addAction(Intent.ACTION_ICONKEY_CHANGED);
 

然后再private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() 加入Intent的receiver动作;

  1. else if (action.equals(Intent.ACTION_ICONKEY_CHANGED)) {  
  2. G, "Received ACTION_ICONKEY_CHANGED");  
  3.     updateIconKeyAction(intent);  
  4. }  

 

方法updateIconKeyAction的定义如下:

 

  1. private final void updateIconKeyAction(Intent intent){  
  2.     int     keycode = intent.getIntExtra("keycode", -1);  
  3.   
  4.     if(keycode != -1){  
  5.         long now = SystemClock.uptimeMillis();  
  6.   
  7.         try {  
  8.             KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0);  
  9.             KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0);  
  10.             (IWindowManager.Stub  
  11.                 .asInterface(ServiceManager.getService("window")))  
  12.                 .injectKeyEvent(down, false);  
  13.             (IWindowManager.Stub  
  14.                 .asInterface(ServiceManager.getService("window")))  
  15.                 .injectKeyEvent(up, false);  
  16.         } catch (RemoteException e) {  
  17.             Log.i("Input", "DeadOjbectException");  
  18.         }  
  19.               
  20.     }  
  21. }  

 

这样,基本上就完成了。

编译一下, 由于新增了一个intent,因此要先make update-api,

  1. ~/donut$ source ./env.sh  
  2. ~/donut$ make update-api  
  3. ~/donut$ make –j8  
  4. ~/donut$ emulator –skin WVGA800  

 

 

另外,如果不是做phone,也可以在StatusBarPolicy.java中将所有phone相关的处理都删掉。

 

 



______________________________________________________________________________________________________________

在Android 2.3状态栏中添加menu,home和back快捷键的方法

1、准备资源,修改XML文
准备几张图,这里我们准备添加home back和menu图标,就需要准备6张图,三张普通状态,三张按下的高亮状态图标:
stat_home.png
stat_home_pressed.png
stat_back.png
stat_back_pressed.png
stat_menu.png
stat_menu_pressed.png
把它们放在frameworks/base/packages/SystemUI/res/drawable/目录下
同时,在frameworks/base/packages/SystemUI/res/drawable 下创建三个imageButton的xml文件
xml_stat_home.xml

1.       <?xml  version = "1.0"  encoding = "utf-8" ?>    
2.       <selector    
3.            xmlns:android = "http://schemas.android.com/apk/res/android" >    
4.            <item    
5.                android:state_focused = "true"    
6.                android:state_pressed = "false"    
7.                android:drawable = "@drawable/stat_home"  />    
8.            <item    
9.                android:state_focused = "true"    
10.             android:state_pressed = "true"    
11.             android:drawable = "@drawable/stat_home_pressed"  />    
12.         <item    
13.             android:state_focused = "false"    
14.             android:state_pressed = "true"    
15.             android:drawable = "@drawable/stat_home_pressed"  />    
16.         <item    
17.             android:drawable = "@drawable/stat_home"  />    
18.    </selector> 



 xml_stat_back.xml

1.      <?xml version="1.0" encoding="utf-8"?>   
2.      <selector   
3.          xmlns:android="http://schemas.android.com/apk/res/android">   
4.          <item   
5.              android:state_focused="true"   
6.              android:state_pressed="false"   
7.              android:drawable="@drawable/stat_back" />   
8.          <item   
9.              android:state_focused="true"   
10.           android:state_pressed="true"   
11.           android:drawable="@drawable/stat_back_pressed" />   
12.       <item   
13.           android:state_focused="false"   
14.           android:state_pressed="true"   
15.           android:drawable="@drawable/stat_back_pressed" />   
16.       <item   
17.           android:drawable="@drawable/stat_back" />   
18.   </selector>    

xml_stat_menu.xml

1.       <?xml  version = "1.0"  encoding = "utf-8" ?>    
2.       <selector    
3.            xmlns:android = "http://schemas.android.com/apk/res/android" >    
4.            <item    
5.                android:state_focused = "true"    
6.                android:state_pressed = "false"    
7.                android:drawable = "@drawable/stat_menu"  />    
8.            <item    
9.                android:state_focused = "true"    
10.             android:state_pressed = "true"    
11.             android:drawable = "@drawable/stat_menu_pressed"  />    
12.         <item    
13.             android:state_focused = "false"    
14.             android:state_pressed = "true"    
15.             android:drawable = "@drawable/stat_menu_pressed"  />    
16.         <item    
17.             android:drawable = "@drawable/stat_menu"  />    
18.    </selector>    

修改status_bar.xml成如下
目录:frameworks/base/packages/SystemUI/res/layout/status_bar.xml

1.       <?xml version="1.0" encoding="utf-8"?>
2.       <!--
3.       /* apps/common/assets/default/default/skins/StatusBar.xml
4.       **
5.       ** Copyright 2006, The Android Open Source Project
6.       **
7.       ** Licensed under the Apache License, Version 2.0 (the "License");
8.       ** you may not use this file except in compliance with the License.
9.       ** You may obtain a copy of the License at
10.     **
11.     **     http://www.apache.org/licenses/LICENSE-2.0
12.     **
13.     ** Unless required by applicable law or agreed to in writing, software
14.     ** distributed under the License is distributed on an "AS IS" BASIS,
15.     ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16.     ** See the License for the specific language governing permissions and
17.     ** limitations under the License.
18.     */
19.     -->
20.      
21.     <!--    android:background="@drawable/status_bar_closed_default_background" -->
22.     <com.android.systemui.statusbar.StatusBarView
23.         xmlns:android="http://schemas.android.com/apk/res/android"
24.         android:background="@drawable/statusbar_background"
25.         android:orientation="vertical"
26.         android:focusable="true"
27.         android:descendantFocusability="afterDescendants"
28.         >
29.      
30.         <LinearLayout android:id="@+id/icons"
31.             android:layout_width="match_parent"
32.             android:layout_height="match_parent"
33.             android:orientation="horizontal">              
34.             <com.android.systemui.statusbar.IconMerger android:id="@+id/notificationIcons"
35.                 android:layout_width="0dip"
36.                 android:layout_weight="1"
37.                 android:layout_height="match_parent"
38.                 android:layout_alignParentLeft="true"
39.                 android:paddingLeft="6dip"
40.                 android:gravity="center_vertical"
41.                 android:orientation="horizontal"/> 
42.                 
43.             <LinearLayout android:id="@+id/statusIcons"
44.                 android:layout_width="wrap_content"
45.                 android:layout_height="match_parent"
46.                 android:layout_alignParentRight="true"
47.                 android:paddingRight="6dip"
48.                 android:gravity="center_vertical"
49.                 android:orientation="horizontal"/>   
50.     <ImageButton android:id="@+id/go_home" 
51.            android:layout_width="32px" 
52.            android:layout_height="32px" 
53.            android:layout_alignParentLeft="true"
54.                     android:paddingLeft="10dip"
55.            android:paddingTop="10dip"
56.                     android:gravity="center_vertical"
57.            android:clickable="true"  
58.            android:background="@drawable/xml_stat_home" 
59.            />  
60.       <ImageButton android:id="@+id/pop_menu" 
61.            android:layout_width="32px" 
62.            android:layout_height="32px" 
63.            android:layout_alignParentRight="true"
64.             android:paddingLeft="10dip"
65.            android:paddingTop="10dip"
66.             android:gravity="center_vertical"
67.             android:orientation="horizontal" 
68.            android:clickable="true"  
69.            android:background="@drawable/xml_stat_menu" 
70.            />         
71.       <ImageButton android:id="@+id/go_back" 
72.            android:layout_width="32px" 
73.            android:layout_height="32px" 
74.            android:layout_alignParentRight="true"
75.             android:paddingLeft="10dip"
76.            android:paddingTop="10dip"
77.             android:gravity="center_vertical"
78.             android:orientation="horizontal" 
79.            android:clickable="true"  
80.            android:background="@drawable/xml_stat_back" 
81.            />                  
82.             <com.android.systemui.statusbar.Clock
83.                 android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon"
84.                 android:layout_width="wrap_content"
85.                 android:layout_height="match_parent"
86.                 android:singleLine="true"
87.                 android:paddingRight="6dip"
88.                 android:gravity="center_vertical|left"
89.                 />
90.         </LinearLayout>
91.             
92.         <LinearLayout android:id="@+id/ticker"
93.             android:layout_width="match_parent"
94.             android:layout_height="match_parent"
95.             android:paddingLeft="6dip"
96.             android:animationCache="false"
97.             android:orientation="horizontal" >
98.             <ImageSwitcher android:id="@+id/tickerIcon"
99.                 android:layout_width="wrap_content"
100.             android:layout_height="match_parent"
101.             android:layout_marginRight="8dip"
102.             >
103.             <com.android.systemui.statusbar.AnimatedImageView
104.                 android:layout_width="25dip"
105.                 android:layout_height="25dip"
106.                 />
107.             <com.android.systemui.statusbar.AnimatedImageView
108.                 android:layout_width="25dip"
109.                 android:layout_height="25dip"
110.                 />
111.         </ImageSwitcher>
112.         <com.android.systemui.statusbar.TickerView android:id="@+id/tickerText"
113.             android:layout_width="0dip"
114.             android:layout_weight="1"
115.             android:layout_height="wrap_content"
116.             android:paddingTop="2dip"
117.             android:paddingRight="10dip">
118.             <TextView
119.                 android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker"
120.                 android:layout_width="match_parent"
121.                 android:layout_height="wrap_content"
122.                 android:singleLine="true"
123.                 />
124.             <TextView
125.                 android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker"
126.                 android:layout_width="match_parent"
127.                 android:layout_height="wrap_content"
128.                 android:singleLine="true"
129.                 />
130.         </com.android.systemui.statusbar.TickerView>
131.     </LinearLayout>
132.  
133.     <com.android.systemui.statusbar.DateView android:id="@+id/date"
134.         android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon"
135.         android:layout_width="wrap_content"
136.         android:layout_height="match_parent"
137.         android:singleLine="true"
138.         android:gravity="center_vertical|left"
139.         android:paddingLeft="6px"
140.         android:paddingRight="6px"
141.         android:background="@drawable/statusbar_background"
142.         />
143.  </com.android.systemui.statusbar.StatusBarView> 


二 为按钮添加动态效果
修改frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarView.java
在类中新增加四个成员(须导入android.widget.ImageButton和android.content.Context):

1.        ImageButton mHomeBtn;  
2.        ImageButton mBackBtn;  
3.        ImageButton mMenuBtn; 
4.        final Context mContext;


增加三个常量:(须导入android.view.KeyEvent;)
 public static final int RESV_KEY_HOME = KeyEvent.KEYCODE_HOME;
 public static final int RESV_KEY_BACK = KeyEvent.KEYCODE_BACK;
 public static final int RESV_KEY_MENU = KeyEvent.KEYCODE_MENU;;
在构造函数StatusBarView中初始化mContext

1.        public StatusBarView(Context context, AttributeSet attrs) {   
2.                super(context, attrs);
3.                 mContext=context;
4.            } 


注意”mContext=context;”须在”super(context, attrs);”后面,不然编译会报错
在onFinishInflate中,获取几个button 的handler,并设置touch事件,添加如下代码:

1.        mHomeBtn  = (ImageButton)findViewById(R.id.go_home);  
2.        mBackBtn  = (ImageButton)findViewById(R.id.go_back);  
3.        mMenuBtn  = (ImageButton)findViewById(R.id.pop_menu);  
4.          
5.        mHomeBtn.setOnTouchListener(homeOnTouch);  
6.        mBackBtn.setOnTouchListener(backOnTouch);  
7.        mMenuBtn.setOnTouchListener(menuOnTouch);  


各button的touch事件添加如下:

1.          void sendIntent ( Intent intent
2.         { 
3.               mContext.sendBroadcast(intent); 
4.          }
5.        private void  sendKeyIntent( int  keycode){  
6.            Intent intent =  new  Intent(Intent.ACTION_ICONKEY_CHANGED);  
7.            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);  
8.            intent.putExtra( "keycode" ,   keycode);  
9.            sendIntent(intent);              
10.      }  
11.        
12.      private  OnTouchListener homeOnTouch =  new  OnTouchListener(){  
13.           //@Override      
14.              public boolean  onTouch(View v, MotionEvent event)   
15.             {     
16.                  // TODO Auto-generated method stub        
17.                  switch  (event.getAction()) {  
18.                      case  MotionEvent.ACTION_UP:  
19.                     {  
20.                      sendKeyIntent(RESV_KEY_HOME);             
21.                  }  
22.                      break ;  
23.                 }  
24.                  return false ;     
25.             }   
26.      };  
27.        
28.      private  OnTouchListener backOnTouch =  new  OnTouchListener(){  
29.           //@Override      
30.              public boolean  onTouch(View v, MotionEvent event)   
31.             {     
32.                  // TODO Auto-generated method stub        
33.                  switch  (event.getAction()) {  
34.                      case  MotionEvent.ACTION_UP:  
35.                     {  
36.                      sendKeyIntent(RESV_KEY_BACK);      
37.                     }  
38.                      break ;  
39.                 }  
40.                  return false ;     
41.             }   
42.      };  
43.        
44.      private  OnTouchListener menuOnTouch =  new  OnTouchListener(){  
45.           //@Override      
46.              public boolean  onTouch(View v, MotionEvent event)   
47.             {     
48.                  // TODO Auto-generated method stub        
49.                  switch  (event.getAction()) {  
50.                      case  MotionEvent.ACTION_UP:  
51.                     {  
52.                      sendKeyIntent(RESV_KEY_MENU);    
53.                     }  
54.                      break ;  
55.                 }  
56.                  return false ;     
57.             }   
58.      }; 


为防止点击statusBar上的按钮, 触发标题栏的expend事件, 修改一下函数onInterceptTouchEvent,点击到不属于button区域时才允许解析Motion的event:

1.             public boolean  onInterceptTouchEvent(MotionEvent event) {  
2.                 if (  (event.getX() > mHomeBtn.getRight())      
3.                    &&  (event.getX() < mMenuBtn.getLeft())){        
4.                     return  mService.interceptTouchEvent(event)      
5.                        ?  true  :  super .onInterceptTouchEvent(event);       
6.                    }       
7.                 return false ;  
8.                 //return mService.interceptTouchEvent(event)                  
9.                 //  ? true : super.onInterceptTouchEvent(event);   
10.          }  
11.      }  


需要自己添加Intent
打开frameworks/base/core/java/android/content/Intent.java,增加下面的内容,由于我们的使用的API不公开,须加上
/**@hide*/,不然编译会报错

1.           /**
2.            * @hide
3.            */   
4.         public static final String ACTION_ICONKEY_CHANGED ="android.intent.action.ICONKEY_CHANGED";
5.             


接收并处理intent
修改StatusBarPolicy.java
目录:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
首先在构造函数中加入Intent的filter,注册号这个intent的receiver。
filter.addAction(Intent.ACTION_ICONKEY_CHANGED); 
接着在private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() 加入Intent的receiver动作;

1.        else if  (action.equals(Intent.ACTION_ICONKEY_CHANGED)) {  
2.                        Log.d(TAG,  "Received ACTION_ICONKEY_CHANGED" );  
3.                        updateIconKeyAction(intent);  
4.                    }  


及处理函数:
须导入以下包
import android.view.IWindowManager;
import android.os.SystemClock;
import android.view.KeyEvent;

1.        private final void  updateIconKeyAction(Intent intent){  
2.             int      keycode = intent.getIntExtra( "keycode" , - 1 );  
3.           IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService( "window" ));  
4.              
5.             if (keycode != - 1 ){  
6.                 long  now = SystemClock.uptimeMillis();  
7.          
8.                   KeyEvent down =  new  KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode,  0 );  
9.                   KeyEvent up =  new  KeyEvent(now, now, KeyEvent.ACTION_UP, keycode,  0 );  
10.        
11.               try  {  
12.                  wm.injectKeyEvent(down,  false );  
13.              } catch  (RemoteException e) {  
14.                  Log.i( "Input" "DeadOjbectException" );  
15.              }  
16.        
17.               try {  
18.                  wm.injectKeyEvent(up,  false );  
19.              } catch (RemoteException e) {  
20.                  Log.i( "Input" "DeadOjbectException" );  
21.              }  
22.          }  
23.      }  


StatusBar通知栏屏蔽按钮
当拉出expand的通知栏时,按钮的响应非常慢,这时最好将按钮给屏蔽掉,我们在 statusBarView.java中增加两个方法:

1.        public void  hiddenHotIcons(){  
2.            mHomeBtn.setVisibility(View.INVISIBLE);  
3.            mBackBtn.setVisibility(View.INVISIBLE);  
4.            mMenuBtn.setVisibility(View.INVISIBLE);  
5.        }  
6.          
7.        public void  showHotIcons(){  
8.            mHomeBtn.setVisibility(View.VISIBLE);  
9.            mBackBtn.setVisibility(View.VISIBLE);  
10.          mMenuBtn.setVisibility(View.VISIBLE);  
11.      }


拉出或收回通知栏中,就可以调用这个函数来显示或隐藏这几个按钮。
修改文件: statusBarService.java
目录:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java

1.        void performExpand() { 
2.           if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded); 
3.           if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) { 
4.             return ;
5.        }
6.        if (mExpanded) {
7.                    return;
8.                }  
9.         mExpanded = true;
10.       makeExpandedVisible();
11.      mStatusBarView.hiddenHotIcons();
12.      updateExpandedViewPos(EXPANDED_FULL_OPEN);
13.      if (false) postStartTracing();
14.      }
15.         void performCollapse() {
16.              if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
17.                      + " mExpandedVisible=" + mExpandedVisible
18.                      + " mTicking=" + mTicking);
19.      
20.              if (!mExpandedVisible) {
21.                  return;
22.              }
23.              mExpandedVisible = false;
24.              visibilityChanged(false);
25.              mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
26.              mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
27.              mExpandedDialog.getWindow().setAttributes(mExpandedParams);
28.              mTrackingView.setVisibility(View.GONE);
29.              mExpandedView.setVisibility(View.GONE);
30.      
31.               mStatusBarView.showHotIcons();
32.      
33.              if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
34.                  setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
35.              }
36.              if (mDateView.getVisibility() == View.VISIBLE) {
37.                  setDateViewVisibility(false, com.android.internal.R.anim.fade_out);
38.              }
39.      
40.              if (!mExpanded) {
41.                  return;
42.              }
43.              mExpanded = false;
44.          }

编译工程 
#source  /opt/android_froyo_smdk/build/envsetup.sh
#export   TARGET_PRODUCT=full_smdkv210
#mmm frameworks/base/
把编译生成的相关文件放进SD卡对应的目录即可,   在伟研科技 WY-S5PV210开发板上的效果如下图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值