咖啡伴侣

呆在上海
posts - 163, comments - 156, trackbacks - 0, articles - 2

在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.         voidsendIntent(Intentintent
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开发板上的效果如下图

只有注册用户登录后才能发表评论。


网站导航: