九鼎创展论坛中文版English
登录 | 立即注册 设为首页收藏本站 切换到宽版
查看: 4648|回复: 0
打印 上一主题 下一主题

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

[复制链接]
跳转到指定楼层
楼主
发表于 2011-11-25 14:21:40 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
Android2.3状态栏中增加menuhomeback快捷键的方法
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下创建三个imageButtonxml文件
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 oragreed to in writing, software
14.  ** distributed under the License isdistributed on an "AS IS" BASIS,
15.  ** WITHOUT WARRANTIES OR CONDITIONS OF ANYKIND, either express or implied.
16.  ** See the License for the specificlanguage 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.      androidrientation="vertical"
26.      android:focusable="true"
27.      android:descendantFocusability="afterDescendants"
28.      >
29.  
30.      <LinearLayoutandroid:id="@+id/icons"
31.          android:layout_width="match_parent"
32.          android:layout_height="match_parent"
33.          androidrientation="horizontal">              
34.          <com.android.systemui.statusbar.IconMergerandroid: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.              androidrientation="horizontal"/>  
42.              
43.          <LinearLayoutandroid: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.              androidrientation="horizontal"/>   
50.  <ImageButtonandroid: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.     <ImageButtonandroid: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.          androidrientation="horizontal"  
68.         android:clickable="true"   
69.         android:background="@drawable/xml_stat_menu"  
70.         />         
71.     <ImageButtonandroid: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.          androidrientation="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.      <LinearLayoutandroid:id="@+id/ticker"
93.          android:layout_width="match_parent"
94.          android:layout_height="match_parent"
95.          android:paddingLeft="6dip"
96.          android:animationCache="false"
97.          androidrientation="horizontal">
98.          <ImageSwitcherandroid: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.TickerViewandroid: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.DateViewandroid: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事件,添加如下代码:
5.   mHomeBtn = (ImageButton)findViewById(R.id.go_home);  
6.   mBackBtn = (ImageButton)findViewById(R.id.go_back);  
7.   mMenuBtn = (ImageButton)findViewById(R.id.pop_menu);  
8.     
9.   mHomeBtn.setOnTouchListener(homeOnTouch);  
10.  mBackBtn.setOnTouchListener(backOnTouch);  
11.  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*/,不然编译会报错
12.     /**
13.       * @hide
14.       */   
15.    public staticfinal String ACTION_ICONKEY_CHANGED ="android.intent.action.ICONKEY_CHANGED";
16.      

  接收并处理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
12.  void performExpand() {
13.     if (SPEW) Slog.d(TAG,"performExpand: mExpanded=" + mExpanded);
14.     if ((mDisabled &StatusBarManager.DISABLE_EXPAND) != 0) {
15.       return ;
16.  }
17.  if (mExpanded) {
18.              return;
19.          }  
20.   mExpanded = true;
21.   makeExpandedVisible();
22. mStatusBarView.hiddenHotIcons();
23.  updateExpandedViewPos(EXPANDED_FULL_OPEN);
24.  if (false) postStartTracing();
25.  }
26.     voidperformCollapse() {
27.          if (SPEW)Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
28.                  +" mExpandedVisible=" + mExpandedVisible
29.                  +" mTicking=" + mTicking);
30.   
31.          if(!mExpandedVisible) {
32.              return;
33.          }
34.          mExpandedVisible = false;
35.          visibilityChanged(false);
36.          mExpandedParams.flags |=WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
37.          mExpandedParams.flags &=~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
38.          mExpandedDialog.getWindow().setAttributes(mExpandedParams);
39.          mTrackingView.setVisibility(View.GONE);
40.          mExpandedView.setVisibility(View.GONE);
41.   
42.          mStatusBarView.showHotIcons();
43.   
44.          if((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
45.              setNotificationIconVisibility(true,com.android.internal.R.anim.fade_in);
46.          }
47.          if(mDateView.getVisibility() == View.VISIBLE) {
48.              setDateViewVisibility(false,com.android.internal.R.anim.fade_out);
49.          }
50.   
51.          if(!mExpanded) {
52.              return;
53.          }
54.          mExpanded =false;
55.      }

    编译工程     #source /opt/android_froyo_smdk/build/envsetup.sh#export   TARGET_PRODUCT=full_smdkv210   #mmm frameworks/base/  把编译生成的相关文件放进SD卡对应的目录即可   最后的效果如图   file:///C:/DOCUME~1/LIUQIM~1/LOCALS~1/Temp/msohtmlclip1/01/clip_image002.jpg   
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳市九鼎创展科技官方论坛 ( 粤ICP备11028681号-2  

GMT+8, 2024-11-23 01:11 , Processed in 0.027019 second(s), 20 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表