九鼎创展论坛
标题: 在Android 2.3状态栏中增加menu,home和back快捷键的方法 [打印本页]
作者: armeasy 时间: 2011-11-25 14:21
标题: 在Android 2.3状态栏中增加menu,home和back快捷键的方法
在Android2.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 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. android
rientation="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. android
rientation="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. android
rientation="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. android
rientation="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. android
rientation="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. android
rientation="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. android
rientation="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.java12. 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
欢迎光临 九鼎创展论坛 (http://bbs.9tripod.com/) |
Powered by Discuz! X3.2 |