在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. 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.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
|