的版本有用,android2.3的代码和架构发生了不少变化,下面说说如何在在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/目录下
同时,[B]在[/B]frameworks/base/packages/SystemUI/res/drawable下创建三个imageButton的xml文件
xml_stat_home.xml
- <?xml version="1.0" encoding="utf-8"?>
- <selector
- xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_focused="true"
- android:state_pressed="false"
- android:drawable="@drawable/stat_home" />
- <item
- android:state_focused="true"
- android:state_pressed="true"
- android:drawable="@drawable/stat_home_pressed" />
- <item
- android:state_focused="false"
- android:state_pressed="true"
- android:drawable="@drawable/stat_home_pressed" />
- <item
- android:drawable="@drawable/stat_home" />
- t;/selector>
xml_stat_back.xml
- <?xml version="1.0" encoding="utf-8"?>
- <selector
- xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_focused="true"
- android:state_pressed="false"
- android:drawable="@drawable/stat_back" />
- <item
- android:state_focused="true"
- android:state_pressed="true"
- android:drawable="@drawable/stat_back_pressed" />
- <item
- android:state_focused="false"
- android:state_pressed="true"
- android:drawable="@drawable/stat_back_pressed" />
- <item
- android:drawable="@drawable/stat_back" />
- </selector>
xml_stat_menu.xml
- <?xml version="1.0" encoding="utf-8"?>
- <selector
- xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:state_focused="true"
- android:state_pressed="false"
- android:drawable="@drawable/stat_menu" />
- <item
- android:state_focused="true"
- android:state_pressed="true"
- android:drawable="@drawable/stat_menu_pressed" />
- <item
- android:state_focused="false"
- android:state_pressed="true"
- android:drawable="@drawable/stat_menu_pressed" />
- <item
- android:drawable="@drawable/stat_menu" />
- t;/selector>
修改status_bar.xml成如下
目录:frameworks/base/packages/SystemUI/res/layout/status_bar.xml
- <?xml version="1.0" encoding="utf-8"?>
- <!--
- /* apps/common/assets/default/default/skins/StatusBar.xml
- **
- ** Copyright 2006, The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- ** http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
- -->
- <!-- android:background="@drawable/status_bar_closed_default_background" -->
- <com.android.systemui.statusbar.StatusBarView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:background="@drawable/statusbar_background"
- android:orientation="vertical"
- android:focusable="true"
- android:descendantFocusability="afterDescendants"
- >
- <LinearLayout android:id="@+id/icons"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
- <com.android.systemui.statusbar.IconMerger android:id="@+id/notificationIcons"
- android:layout_width="0dip"
- android:layout_weight="1"
- android:layout_height="match_parent"
- android:layout_alignParentLeft="true"
- android:paddingLeft="6dip"
- android:gravity="center_vertical"
- android:orientation="horizontal"/>
- <LinearLayout android:id="@+id/statusIcons"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_alignParentRight="true"
- android:paddingRight="6dip"
- android:gravity="center_vertical"
- android:orientation="horizontal"/>
- <ImageButton android:id="@+id/go_home"
- android:layout_width="32px"
- android:layout_height="32px"
- android:layout_alignParentLeft="true"
- android:paddingLeft="10dip"
- android:paddingTop="10dip"
- android:gravity="center_vertical"
- android:clickable="true"
- android:background="@drawable/xml_stat_home"
- />
- <ImageButton android:id="@+id/pop_menu"
- android:layout_width="32px"
- android:layout_height="32px"
- android:layout_alignParentRight="true"
- android:paddingLeft="10dip"
- android:paddingTop="10dip"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:clickable="true"
- android:background="@drawable/xml_stat_menu"
- />
- <ImageButton android:id="@+id/go_back"
- android:layout_width="32px"
- android:layout_height="32px"
- android:layout_alignParentRight="true"
- android:paddingLeft="10dip"
- android:paddingTop="10dip"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:clickable="true"
- android:background="@drawable/xml_stat_back"
- />
- <com.android.systemui.statusbar.Clock
- android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:singleLine="true"
- android:paddingRight="6dip"
- android:gravity="center_vertical|left"
- />
- </LinearLayout>
- <LinearLayout android:id="@+id/ticker"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingLeft="6dip"
- android:animationCache="false"
- android:orientation="horizontal" >
- <ImageSwitcher android:id="@+id/tickerIcon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginRight="8dip"
- >
- <com.android.systemui.statusbar.AnimatedImageView
- android:layout_width="25dip"
- android:layout_height="25dip"
- />
- <com.android.systemui.statusbar.AnimatedImageView
- android:layout_width="25dip"
- android:layout_height="25dip"
- />
- </ImageSwitcher>
- <com.android.systemui.statusbar.TickerView android:id="@+id/tickerText"
- android:layout_width="0dip"
- android:layout_weight="1"
- android:layout_height="wrap_content"
- android:paddingTop="2dip"
- android:paddingRight="10dip">
- <TextView
- android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- />
- <TextView
- android:textAppearance="@*android:style/TextAppearance.StatusBar.Ticker"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- />
- </com.android.systemui.statusbar.TickerView>
- </LinearLayout>
- <com.android.systemui.statusbar.DateView android:id="@+id/date"
- android:textAppearance="@*android:style/TextAppearance.StatusBar.Icon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:singleLine="true"
- android:gravity="center_vertical|left"
- android:paddingLeft="6px"
- android:paddingRight="6px"
- android:background="@drawable/statusbar_background"
- />
- lt;/com.android.systemui.statusbar.StatusBarView>
二 为按钮添加动态效果
改frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarView.java 在类中新增加四个成员(须导入android.widget.ImageButton和android.content.Context):
- ImageButton mHomeBtn;
- ImageButton mBackBtn;
- ImageButton mMenuBtn;
- 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
- public StatusBarView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mContext=context;
- }
注意”mContext=context;”须在”super(context,attrs);”后面,不然编译会报错
在onFinishInflate中,获取几个button 的handler,并设置touch事件,添加如下代码:
- mHomeBtn = (ImageButton)findViewById(R.id.go_home);
- mBackBtn = (ImageButton)findViewById(R.id.go_back);
- mMenuBtn = (ImageButton)findViewById(R.id.pop_menu);
- mHomeBtn.setOnTouchListener(homeOnTouch);
- mBackBtn.setOnTouchListener(backOnTouch);
- mMenuBtn.setOnTouchListener(menuOnTouch);
各button的touch事件添加如下:
- void sendIntent(Intent intent)
- {
- mContext.sendBroadcast(intent);
- }
- private void sendKeyIntent(int keycode){
- Intent intent = new Intent(Intent.ACTION_ICONKEY_CHANGED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- intent.putExtra("keycode", keycode);
- sendIntent(intent);
- }
- private OnTouchListener homeOnTouch = new OnTouchListener(){
- //@Override
- public boolean onTouch(View v, MotionEvent event)
- {
- // TODO Auto-generated method stub
- switch (event.getAction()) {
- case MotionEvent.ACTION_UP:
- {
- sendKeyIntent(RESV_KEY_HOME);
- }
- break;
- }
- return false;
- }
- };
- private OnTouchListener backOnTouch = new OnTouchListener(){
- //@Override
- public boolean onTouch(View v, MotionEvent event)
- {
- // TODO Auto-generated method stub
- switch (event.getAction()) {
- case MotionEvent.ACTION_UP:
- {
- sendKeyIntent(RESV_KEY_BACK);
- }
- break;
- }
- return false;
- }
- };
- private OnTouchListener menuOnTouch = new OnTouchListener(){
- //@Override
- public boolean onTouch(View v, MotionEvent event)
- {
- // TODO Auto-generated method stub
- switch (event.getAction()) {
- case MotionEvent.ACTION_UP:
- {
- sendKeyIntent(RESV_KEY_MENU);
- }
- break;
- }
- return false;
- }
- };
为防止点击statusBar上的按钮, 触发标题栏的expend事件, 修改一下函数onInterceptTouchEvent,点击到不属于button区域时才允许解析Motion的event:
- public boolean onInterceptTouchEvent(MotionEvent event) {
- if( (event.getX() > mHomeBtn.getRight())
- && (event.getX() < mMenuBtn.getLeft())){
- return mService.interceptTouchEvent(event)
- ? true : super.onInterceptTouchEvent(event);
- }
- return false;
- //return mService.interceptTouchEvent(event)
- // ? true : super.onInterceptTouchEvent(event);
- }
- }
需要自己添加Intent 打开frameworks/base/core/java/android/content/Intent.java,增加下面的内容,由于我们的使用的API不公开,须加上/**@hide*/,不然编译会报错
- /**
- * @hide
- */
- public static final String ACTION_ICONKEY_CHANGED ="android.intent.action.ICONKEY_CHANGED";
接收并处理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 = newBroadcastReceiver() 加入Intent的receiver动作;
- else if (action.equals(Intent.ACTION_ICONKEY_CHANGED)) {
- Log.d(TAG, "Received ACTION_ICONKEY_CHANGED");
- updateIconKeyAction(intent);
- }
及处理函数: 须导入以下包 import android.view.IWindowManager; import android.os.SystemClock; import android.view.KeyEvent;
[java] view plain copy
- private final void updateIconKeyAction(Intent intent){
- int keycode = intent.getIntExtra("keycode", -1);
- IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
- if(keycode != -1){
- long now = SystemClock.uptimeMillis();
- KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0);
- KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0);
- try {
- wm.injectKeyEvent(down, false);
- }catch (RemoteException e) {
- Log.i("Input", "DeadOjbectException");
- }
- try{
- wm.injectKeyEvent(up, false);
- }catch(RemoteException e) {
- Log.i("Input", "DeadOjbectException");
- }
- }
- }
StatusBar通知栏屏蔽按钮 当拉出expand的通知栏时,按钮的响应非常慢,这时最好将按钮给屏蔽掉,我们在 statusBarView.java中增加两个方法:
- public void hiddenHotIcons(){
- mHomeBtn.setVisibility(View.INVISIBLE);
- mBackBtn.setVisibility(View.INVISIBLE);
- mMenuBtn.setVisibility(View.INVISIBLE);
- }
- public void showHotIcons(){
- mHomeBtn.setVisibility(View.VISIBLE);
- mBackBtn.setVisibility(View.VISIBLE);
- mMenuBtn.setVisibility(View.VISIBLE);
拉出或收回通知栏中,就可以调用这个函数来显示或隐藏这几个按钮。
修改文件:statusBarService.java
目录:frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
[java] view plain copy
- void performExpand() {
- if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded);
- if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
- return ;
- }
- if (mExpanded) {
- return;
- }
- mExpanded = true;
- makeExpandedVisible();
- mStatusBarView.hiddenHotIcons();
- updateExpandedViewPos(EXPANDED_FULL_OPEN);
- if (false) postStartTracing();
- }
- void performCollapse() {
- if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
- + " mExpandedVisible=" + mExpandedVisible
- + " mTicking=" + mTicking);
- if (!mExpandedVisible) {
- return;
- }
- mExpandedVisible = false;
- visibilityChanged(false);
- mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- mExpandedDialog.getWindow().setAttributes(mExpandedParams);
- mTrackingView.setVisibility(View.GONE);
- mExpandedView.setVisibility(View.GONE);
- mStatusBarView.showHotIcons();
- if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
- setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
- }
- if (mDateView.getVisibility() == View.VISIBLE) {
- setDateViewVisibility(false, com.android.internal.R.anim.fade_out);
- }
- if (!mExpanded) {
- return;
- }
- mExpanded = false;
- }
最后编译:1. 先更新API,make update-api
2. mmm frameworks/base/packages/SystemUI