之前看了

http://blog.csdn.net/freshui/archive/2010/11/24/6033377.aspx

http://blog.csdn.net/freshui/archive/2010/07/15/5738115.aspx

两篇文章说到如何在Android状态栏中增加menu,home和back快捷键的方法,经过研究发现上面的两篇文章的方法只是对android2.2以前

的版本有用,android2.3的代码和架构发生了不少变化,下面说说如何在在android2.3实现在状态栏中增加menu,home和back快捷键,本文大部分引用上面两篇文章,感谢两篇博文作者提供参考。

1、准备资源,修改XML

准备几张图,这里我们准备添加home backmenu图标,就需要准备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 下创建三个imageButtonxml文件

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" /> </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" /> </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" /> </com.android.systemui.statusbar.StatusBarView>

为按钮添加动态效果

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarView.java
在类中新增加四个成员(须导入android.widget.ImageButtonandroid.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);

buttontouch事件添加如下:

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区域时才允许解析Motionevent

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

 首先在构造函数中加入Intentfilter,注册号这个intentreceiver
filter.addAction(Intent.ACTION_ICONKEY_CHANGED);
接着在private BroadcastReceiver mIntentReceiver = newBroadcastReceiver() 加入Intentreceiver动作;

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;
  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
    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;    } 
 编译工程(使用的是伟研的WY-S5PV210开发板) 
 #source    #/opt/android_froyo_smdk/build/envsetup.sh
#export TARGET_PRODUCT=full_smdkv210
#mmm frameworks/base/
把编译生成的相关文件放进SD卡对应的目录即可,最后的效果如图
   

更多相关文章

  1. C语言函数的递归(上)
  2. Android学习笔记--Binder
  3. 3. Android(安卓)MultiMedia框架完全解析 - setDataSource继续分
  4. [android] HttpURLConnection的初步学习
  5. Binder框架 -- android AIDL 的使用
  6. Android中JNI编程的那些事儿
  7. 【转】Android(安卓)statusBar添加back,home,menu按钮
  8. Android研究-linux内核启动到android系统
  9. android 开发的一个小警告

随机推荐

  1. Html 转换 Txt
  2. Android(安卓)Binder
  3. Android中将layout_width或layout_height
  4. Android(安卓)Spinner 使用初步
  5. Android(安卓)HAL技术详解
  6. 解决了在Android原生TextView中,当text长
  7. Eclipse 点击 Run 自动生成 out 文件的错
  8. Android定时器AlarmManager和Timer的区别
  9. Dialog使用findViewById 报空指针异常
  10. 浅析Android中build.gradle的实用技巧