由于完全改了status bar,建议先做几张png图片,加到
Frameworks/base/core/res/res/drawable
下。最好做一张背景图,替换 statusbar_background.png
另外我又加了几张icon,分别是home menu和back的正常和按下状态。
这些图片为:
frameworks\base\core\res\res\drawable\ic_menu_back_pressed.png
frameworks\base\core\res\res\drawable\ic_menu_home_pressed.png
frameworks\base\core\res\res\drawable\ic_menu_more_pressed.png
frameworks\base\core\res\res\drawable\ic_volume_down_pressed.png
frameworks\base\core\res\res\drawable\ic_volume_up_pressed.png
frameworks\base\core\res\res\drawable\ic_menu_back.png
frameworks\base\core\res\res\drawable\ic_menu_home.png
frameworks\base\core\res\res\drawable\ic_menu_more.png
frameworks\base\core\res\res\drawable\ic_volume_down.png
frameworks\base\core\res\res\drawable\ic_volume_up.png
修改步骤为:
一.修改xml界面
1.创建按钮
frameworks\base\core\res\res\drawable\btn_sbicon_back.xml
frameworks\base\core\res\res\drawable\btn_sbicon_home.xml
frameworks\base\core\res\res\drawable\btn_sbicon_menu.xml
frameworks\base\core\res\res\drawable\btn_sbicon_vol_down.xml
frameworks\base\core\res\res\drawable\btn_sbicon_vol_up.xml
基结构如下:
<?xml version="1.0"encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
</selector>
2. 增加图标
更改整个status bar,我的方法是:
修改status bar的layerout文件:
Frameworks/base/core/res/res/layout/status_bar.xml
在原来的linearlayout中新增 image view
<?xml version="1.0"encoding="utf-8"?>
<com.android.server.status.StatusBarViewxmlns:android="http://schemas.android.com/apk/res/android"
</com.android.server.status.StatusBarView>
这样做的好处就是简单。同时保证home、menu、back按钮,不受它本来的约束。这样statusbar上即可看到这些按钮了。
图标的位置,可通过修改 paddingRight, paddingLeft 和paddingTop的值达到最佳视觉效果。
3. 修改status bar的高度。
既然要在status bar上增加那么几个按钮,当然是想要使用触摸操作的,android自带的statusbar高度太小,不适用。对于7寸屏的话,50pixel的高度应该是差不多了。
修改高度很简单,修改frameworks/base/core/res/res/values/dimens.xml的status_bar_height属性
也可以更改状态栏Icon的大小,frameworks\base\core\res\res\layout\status_bar_icon.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
当然,如果相改title的高度,可以修改Frameworks/base/core/res/res/values/themes.xml中的Windowattributes的windowTitleSize值
编译运行一下:
~/donut$ source ./env.sh
~/donut$ make –j8
~/donut$ emulator –skin WVGA800
~/donut$ source ./env.sh
~/donut$ make –j8
~/donut$ emulator –skin WVGA800
看状态栏是不是改变了?
二 为按钮添加模拟按键
修改frameworks\base\services\java\com\android\server\status\StatusBarView.java
1.添加各个图片按钮的引用,
android.widget.LinearLayout keysLayout;
android.widget.ImageView btnHome;
android.widget.ImageView btnBack;
android.widget.ImageView btnMenu;
android.widget.ImageView btnVolUp;
android.widget.ImageView btnVolDown;
2.修改onFinishInflate()函数,各个图片ID在上面的status_bar.xml中已经定义
@Override
protected void onFinishInflate() {
}
3.添加各个按钮的事件监听Listener
android.view.View.OnClickListener mKeysListener = newandroid.view.View.OnClickListener(){
public void onClick(View v) {
switch (v.getId()) {
case R.id.status_home:
case R.id.status_back:
case R.id.status_menu:
case R.id.status_vol_up:
case R.id.status_vol_down:
default:
}
}};
4.添加模拟按键处理
private static final int KEY_HOME = 1000;
private static final int KEY_BACK = 1001;
private static final int KEY_MENU = 1002;
private static final int KEY_VOL_UP = 1003;
private static final int KEY_VOL_DOWN = 1004;
private Handler mKeysHandler = new Handler(){
public void handleMessage(Message msg) {
case KEY_HOME:
case KEY_BACK:
case KEY_MENU:
case KEY_VOL_UP:
case KEY_VOL_DOWN:
default:
}
}
};
5.避免在按下这几个按钮时,触发下拉Notification视图,影响性能
修改onInterceptTouchEvent(MotionEvent event)函数
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (keysLayout.getRight() < event.getX())
return false;
}
这样,基本上就完成了。
编译一下
~/donut$ source./env.sh
~/donut$ make update-api
~/donut$ make –j8
~/donut$ emulator –skin WVGA800
~/donut$ source ./env.sh
~/donut$ make update-api
~/donut$ make –j8
~/donut$ emulator –skin WVGA800
补充:在打开StatusBarExpandView时按模拟按键,会出现停顿的原因分析
我们先看一下执行流程
在com.android.server.WindowManagerService.injectKeyEvent(KeyEvent,boolean)函数中我们可以看到实际上是调用dispatchKey(newEvent, pid,uid)函数,这个dispatchKey函数中:
需要先找到当前的焦点focusObj(focusObj:WindowState
通过打印Log显示是我们的KeyEvent.Action_Down事件一直不能mFinished,这就要跟踪ViewRoot,发现每次在模拟的KeyEvent.Action_Down事件的Message根本不能被处理,原因是StatusBarView的TouchEvent没有处理完成,并且与模拟的KeyEvent.Action_Down事件在MessageQueue的next函数中卡住了而ViewRoot本身就是一个Handler,大量的Message从此经过,而StatusBar的ViewRoot既要处理Touch事件也要处理模拟按键,就出现了这种竞态死锁的现象。
延迟发送模拟的KeyEvent是我目前采用的解决方式,上面的例子中sendKey函数已经体现