在android的状态栏(statusbar)中增加menu,home和back快捷键的方法
2010-10-27 17:01
429 查看
由于完全改了
status bar
,建议先做几张
png
图片,加到
Frameworks/base/core/res/res/drawable
下。最好做一张背景图,替换
statusbar_background.png
另外我又加了几张
icon
,分别是
home menu
和
back
的正常和按下状态。
这些图片为:
stat_home.png
stat_home_pressed.png
stat_back.png
stat_back_pressed.png
stat_menu.png
stat_menu_pressed.png
修改步骤为:
一.
1.
status bar
避免不要要对源码大刀修一下。我的该法是:
修改
status bar
的
layerout
文件:
Frameworks/base/core/res/res/layout/status_bar.xml
在原来的
linearlayout
中新增三个
image view
view plain
copy to clipboard
print
?
<
LinearLayout
android:id
=
"@+id/icons"
android:layout_width
=
"fill_parent"
android:layout_height
=
"fill_parent"
android:orientation
=
"horizontal"
>
<
ImageView
android:id
=
"@+id/status_home"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"top"
android:paddingTop
=
"6dip"
android:paddingRight
=
"10dip"
android:paddingLeft
=
"10dip"
android:src
=
"@drawable/stat_home"
/>
<
com.android.server.status.IconMerger
android:id
=
"@+id/notificationIcons"
android:layout_width
=
"0dip"
android:layout_weight
=
"1"
android:layout_height
=
"fill_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
=
"fill_parent"
android:layout_alignParentRight
=
"true"
android:paddingRight
=
"6dip"
android:gravity
=
"center_vertical"
android:orientation
=
"horizontal"
/>
<
ImageView
android:id
=
"@+id/status_menu"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"top"
android:paddingTop
=
"6dip"
android:paddingLeft
=
"10dip"
android:paddingRight
=
"10dip"
android:src
=
"@drawable/stat_menu"
/>
<
ImageView
android:id
=
"@+id/status_back"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"top"
android:paddingTop
=
"6dip"
android:paddingRight
=
"10dip"
android:paddingLeft
=
"10dip"
android:src
=
"@drawable/stat_back"
/>
/LinearLayout>
这样做的好处就是简单。同时保证最右端是
home
按钮,最左端是
back
按钮,不受它本来的约束。这样
status bar
上即可看到这些按钮了。
图标的位置,可通过修改
paddingRight
,
paddingLeft
和
paddingTop
的值达到最佳视觉效果。
2.
status bar
上增加那么几个按钮,当然是想要使用触摸操作的,
android
自带的
status bar
高度太小,不适用。对于
7
寸屏的话,
50pixel
的高度应该是差不多了。
修改高度很简单,如我转的
shinning mm
的博文。
修改
frameworks/base/core/res/res/values/dimens.xml
的
status_bar_height
属性
<!-- Height of the status bar -->
<dimen name="status_bar_height">50dip</dimen>
当然,如果相改
title
的高度,可以修改
Frameworks
/base/core/res/res/values/themes.xml
中的
Window attributes
的
windowTitleSize
值,不过我觉得没必要,改了反倒不好看了
:)
编译运行一下:
view plain
copy to clipboard
print
?
~/donut$ source ./env.sh
~/donut$ make –j8
~/donut$ emulator –skin WVGA800
,
看状态栏是不是改变了?
二
hilight
,松开或者移出后恢复的动作。这一块,我是通过修改
frameworks/base/services/java/com/android/server/status/StatusBarView.java
实现的。
1.
import android.widget.ImageView;
):
view plain
copy to clipboard
print
?
ImageView mHomeIcon;
ImageView mBackIcon;
ImageView mMenuIcon;
同时增加三个常量,表示这些
icon
对应的键值
(
这需要
import android.view.KeyEvent;)
view plain
copy to clipboard
print
?
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;;
在
onFinishInflate()
中,获得实际的对象:
view plain
copy to clipboard
print
?
mHomeIcon = (ImageView)findViewById(R.id.status_home);
mBackIcon = (ImageView)findViewById(R.id.status_back);
mMenuIcon = (ImageView)findViewById(R.id.status_menu);
这三个对象就是我们在
status_bar.xml
中添加的。
2.
添加触摸处理。
首先,应该判断是那个图标被按下,这个我们在
StatusBarView.Java
的
onTouchEvent
中来判断。
这里,我做了一个小的按键状态,已方便处理按下、弹起和移出的动作。
首先增加两个状态成员:
view plain
copy to clipboard
print
?
int
mResvKeyState = -1;
//记住的上次按键状态, -1为无状态。
int
mResvKeyCode = -1;
//记住的上次按键值,-1为无状态。
这样我的
onTouchEvent
就变成这样了:
view plain
copy to clipboard
print
?
@Override
public
boolean
onTouchEvent(MotionEvent event) {
if
(mService.mExpanded==
true
|| mService.mTracking==
true
){
if
(event.getAction() != MotionEvent.ACTION_DOWN) {
mService.interceptTouchEvent(event);
}
return
true
;
}
if
(mResvKeyState == -
1
)
// remembered key state, no reserve
{
switch
(getResvKeyArea(event)){
case
RESV_KEY_HOME:
case
RESV_KEY_BACK:
case
RESV_KEY_MENU:
{
mResvKeyState = event.getAction();
mResvKeyCode = getResvKeyArea(event);
updateResvKeyIcon(mResvKeyState, mResvKeyCode);
}
break
;
default
:
if
(event.getAction() != MotionEvent.ACTION_DOWN) {
mService.interceptTouchEvent(event);
}
}
}else
{
mResvKeyState = event.getAction(); // new state
if
(mResvKeyState == MotionEvent.ACTION_MOVE){
if
(mResvKeyCode != getResvKeyArea(event)){
/* out of bound, resume the icon */
updateResvKeyIcon(MotionEvent.ACTION_UP, mResvKeyCode);
mResvKeyCode = -1
;
mResvKeyState = -1
;
}
}else
if
(mResvKeyState == MotionEvent.ACTION_UP){
updateResvKeyIcon(mResvKeyState, mResvKeyCode);
mResvKeyCode = -1
;
mResvKeyState = -1
;
}else
{
Log.d(TAG, "state machine error! Never be here!"
);
}
}
return
true
;
}
里面用到的两个private方法简单实现如下:
view plain
copy to clipboard
print
?
private
int
getResvKeyArea(MotionEvent
event
)
{
if
( (
event
.getX() <= mHomeIcon.getRight())
&& (event
.getY() <=
this
.getHeight()) ){
return
RESV_KEY_HOME;
}
else
if
( (
event
.getX() >= mBackIcon.getLeft())
&& (event
.getY() <=
this
.getHeight()) ){
return
RESV_KEY_BACK;
}
else
if
( (
event
.getX() >= mMenuIcon.getLeft())
&& (event
.getY() <=
this
.getHeight()) ){
return
RESV_KEY_MENU;
}else
return
-1;
}
private
int
updateResvKeyIcon(
int
state,
int
key)
{
if
(key == RESV_KEY_BACK){
if
(state == MotionEvent.ACTION_UP){
mBackIcon.setImageResource(com.android.internal
.R.drawable.stat_back);
}else
if
(state == MotionEvent.ACTION_DOWN){
mBackIcon.setImageResource(com.android.internal
.R.drawable.stat_back_pressed);
}
}else
if
(key == RESV_KEY_HOME){
if
(state == MotionEvent.ACTION_UP){
mHomeIcon.setImageResource(com.android.internal
.R.drawable.stat_home);
}else
if
(state == MotionEvent.ACTION_DOWN){
mHomeIcon.setImageResource(com.android.internal
.R.drawable.stat_home_pressed);
}
}else
if
(key == RESV_KEY_MENU){
if
(state == MotionEvent.ACTION_UP){
mMenuIcon.setImageResource(com.android.internal
.R.drawable.stat_menu);
}else
if
(state == MotionEvent.ACTION_DOWN){
mMenuIcon.setImageResource(com.android.internal
.R.drawable.stat_menu_pressed);
}
}
return
0;
}
同时,我不想再在按下这些icon的时候,触发下拉动作,我也改了onInterceptTouchEvent函数:
view plain
copy to clipboard
print
?
@Override
public
boolean
onInterceptTouchEvent(MotionEvent event) {
if
( (event.getX() > mHomeIcon.getRight())
&& (event.getX() < mMenuIcon.getLeft())){
return
mService.interceptTouchEvent(event)
? true
:
super
.onInterceptTouchEvent(event);
}
return
false
;
}
再编译一下,看一下结果
:
)
是不是能动了?
三,添加相应事件
1. 添加新的intent
首先是新增一条
intent
,
在
framework/base/core/java/android/content/intent.java
中增加
view plain
copy to clipboard
print
?
@SdkConstant
(SdkConstantType.BROADCAST_INTENT_ACTION)
public
static
final
String ACTION_ICONKEY_CHANGED =
"android.intent.action.ICONKEY_CHANGED"
;
view plain
copy to clipboard
print
?
Intent intent =
new
Intent(Intent.ACTION_ICONKEY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra("keycode"
, mResvKeyCode);
mService.sendIntent(intent);
这个intent是只有注册的接收者才能接收。
这里,我们是通过StatusBarService来发送这个intent的。
在StatusBarService.java中新增一个方法:
view plain
copy to clipboard
print
?
void
sendIntent(Intent intent)
{
mContext.sendBroadcast(intent);
}
首先,在构造函数中加入Intent的filter,注册号这个intent的receiver。
filter.addAction(Intent.ACTION_ICONKEY_CHANGED);
然后再private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() 加入Intent的receiver动作;
view plain
copy to clipboard
print
?
else
if
(action.equals(Intent.ACTION_ICONKEY_CHANGED)) {
G, "Received ACTION_ICONKEY_CHANGED"
);
updateIconKeyAction(intent);
}
方法updateIconKeyAction的定义如下:
view plain
copy to clipboard
print
?
private
final
void
updateIconKeyAction(Intent intent){
int
keycode = intent.getIntExtra(
"keycode"
, -
1
);
if
(keycode != -
1
){
long
now = SystemClock.uptimeMillis();
try
{
KeyEvent down = new
KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode,
0
);
KeyEvent up = new
KeyEvent(now, now, KeyEvent.ACTION_UP, keycode,
0
);
(IWindowManager.Stub
.asInterface(ServiceManager.getService("window"
)))
.injectKeyEvent(down, false
);
(IWindowManager.Stub
.asInterface(ServiceManager.getService("window"
)))
.injectKeyEvent(up, false
);
} catch
(RemoteException e) {
Log.i("Input"
,
"DeadOjbectException"
);
}
}
}
这样,基本上就完成了。
编译一下, 由于新增了一个intent,因此要先make update-api,
view plain
copy to clipboard
print
?
~/donut$ source ./env.sh
~/donut$ make update-api
~/donut$ make –j8
~/donut$ emulator –skin WVGA800
另外,如果不是做phone,也可以在StatusBarPolicy.java中将所有phone相关的处理都删掉。
status bar
,建议先做几张
png
图片,加到
Frameworks/base/core/res/res/drawable
下。最好做一张背景图,替换
statusbar_background.png
另外我又加了几张
icon
,分别是
home menu
和
back
的正常和按下状态。
这些图片为:
stat_home.png
stat_home_pressed.png
stat_back.png
stat_back_pressed.png
stat_menu.png
stat_menu_pressed.png
修改步骤为:
一.
修改
xml
界面
1.
增加图标
当然,更改整个
status bar
避免不要要对源码大刀修一下。我的该法是:
修改
status bar
的
layerout
文件:
Frameworks/base/core/res/res/layout/status_bar.xml
在原来的
linearlayout
中新增三个
image view
view plain
copy to clipboard
?
<
LinearLayout
android:id
=
"@+id/icons"
android:layout_width
=
"fill_parent"
android:layout_height
=
"fill_parent"
android:orientation
=
"horizontal"
>
<
ImageView
android:id
=
"@+id/status_home"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"top"
android:paddingTop
=
"6dip"
android:paddingRight
=
"10dip"
android:paddingLeft
=
"10dip"
android:src
=
"@drawable/stat_home"
/>
<
com.android.server.status.IconMerger
android:id
=
"@+id/notificationIcons"
android:layout_width
=
"0dip"
android:layout_weight
=
"1"
android:layout_height
=
"fill_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
=
"fill_parent"
android:layout_alignParentRight
=
"true"
android:paddingRight
=
"6dip"
android:gravity
=
"center_vertical"
android:orientation
=
"horizontal"
/>
<
ImageView
android:id
=
"@+id/status_menu"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"top"
android:paddingTop
=
"6dip"
android:paddingLeft
=
"10dip"
android:paddingRight
=
"10dip"
android:src
=
"@drawable/stat_menu"
/>
<
ImageView
android:id
=
"@+id/status_back"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_gravity
=
"top"
android:paddingTop
=
"6dip"
android:paddingRight
=
"10dip"
android:paddingLeft
=
"10dip"
android:src
=
"@drawable/stat_back"
/>
/LinearLayout>
<LinearLayout android:id="@+id/icons" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal"> <ImageView android:id="@+id/status_home" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" android:paddingTop="6dip" android:paddingRight="10dip" android:paddingLeft="10dip" android:src="@drawable/stat_home" /> <com.android.server.status.IconMerger android:id="@+id/notificationIcons" android:layout_width="0dip" android:layout_weight="1" android:layout_height="fill_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="fill_parent" android:layout_alignParentRight="true" android:paddingRight="6dip" android:gravity="center_vertical" android:orientation="horizontal"/> <ImageView android:id="@+id/status_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" android:paddingTop="6dip" android:paddingLeft="10dip" android:paddingRight="10dip" android:src="@drawable/stat_menu" /> <ImageView android:id="@+id/status_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" android:paddingTop="6dip" android:paddingRight="10dip" android:paddingLeft="10dip" android:src="@drawable/stat_back" /> </LinearLayout>
这样做的好处就是简单。同时保证最右端是
home
按钮,最左端是
back
按钮,不受它本来的约束。这样
status bar
上即可看到这些按钮了。
图标的位置,可通过修改
paddingRight
,
paddingLeft
和
paddingTop
的值达到最佳视觉效果。
2.
修改
status bar
的高度。
既然要在
status bar
上增加那么几个按钮,当然是想要使用触摸操作的,
android
自带的
status bar
高度太小,不适用。对于
7
寸屏的话,
50pixel
的高度应该是差不多了。
修改高度很简单,如我转的
shinning mm
的博文。
修改
frameworks/base/core/res/res/values/dimens.xml
的
status_bar_height
属性
<!-- Height of the status bar -->
<dimen name="status_bar_height">50dip</dimen>
当然,如果相改
title
的高度,可以修改
Frameworks
/base/core/res/res/values/themes.xml
中的
Window attributes
的
windowTitleSize
值,不过我觉得没必要,改了反倒不好看了
:)
编译运行一下:
view plain
copy to clipboard
?
~/donut$ source ./env.sh
~/donut$ make –j8
~/donut$ emulator –skin WVGA800
~/donut$ source ./env.sh ~/donut$ make –j8 ~/donut$ emulator –skin WVGA800
,
看状态栏是不是改变了?
二
为按钮添加动态效果
添加动态效果,就是触摸按下
hilight
,松开或者移出后恢复的动作。这一块,我是通过修改
frameworks/base/services/java/com/android/server/status/StatusBarView.java
实现的。
1.
获取
statusbar
中新增加的
icon
的
handler
。
在类中新增加三个成员(这需要
import android.widget.ImageView;
):
view plain
copy to clipboard
?
ImageView mHomeIcon;
ImageView mBackIcon;
ImageView mMenuIcon;
ImageView mHomeIcon; ImageView mBackIcon; ImageView mMenuIcon;
同时增加三个常量,表示这些
icon
对应的键值
(
这需要
import android.view.KeyEvent;)
view plain
copy to clipboard
?
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;;
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;;
在
onFinishInflate()
中,获得实际的对象:
view plain
copy to clipboard
?
mHomeIcon = (ImageView)findViewById(R.id.status_home);
mBackIcon = (ImageView)findViewById(R.id.status_back);
mMenuIcon = (ImageView)findViewById(R.id.status_menu);
mHomeIcon = (ImageView)findViewById(R.id.status_home); mBackIcon = (ImageView)findViewById(R.id.status_back); mMenuIcon = (ImageView)findViewById(R.id.status_menu);
这三个对象就是我们在
status_bar.xml
中添加的。
2.
添加触摸处理。
首先,应该判断是那个图标被按下,这个我们在
StatusBarView.Java
的
onTouchEvent
中来判断。
这里,我做了一个小的按键状态,已方便处理按下、弹起和移出的动作。
首先增加两个状态成员:
view plain
copy to clipboard
?
int
mResvKeyState = -1;
//记住的上次按键状态, -1为无状态。
int
mResvKeyCode = -1;
//记住的上次按键值,-1为无状态。
int mResvKeyState = -1; //记住的上次按键状态, -1为无状态。 int mResvKeyCode = -1; //记住的上次按键值,-1为无状态。
这样我的
onTouchEvent
就变成这样了:
view plain
copy to clipboard
?
@Override
public
boolean
onTouchEvent(MotionEvent event) {
if
(mService.mExpanded==
true
|| mService.mTracking==
true
){
if
(event.getAction() != MotionEvent.ACTION_DOWN) {
mService.interceptTouchEvent(event);
}
return
true
;
}
if
(mResvKeyState == -
1
)
// remembered key state, no reserve
{
switch
(getResvKeyArea(event)){
case
RESV_KEY_HOME:
case
RESV_KEY_BACK:
case
RESV_KEY_MENU:
{
mResvKeyState = event.getAction();
mResvKeyCode = getResvKeyArea(event);
updateResvKeyIcon(mResvKeyState, mResvKeyCode);
}
break
;
default
:
if
(event.getAction() != MotionEvent.ACTION_DOWN) {
mService.interceptTouchEvent(event);
}
}
}else
{
mResvKeyState = event.getAction(); // new state
if
(mResvKeyState == MotionEvent.ACTION_MOVE){
if
(mResvKeyCode != getResvKeyArea(event)){
/* out of bound, resume the icon */
updateResvKeyIcon(MotionEvent.ACTION_UP, mResvKeyCode);
mResvKeyCode = -1
;
mResvKeyState = -1
;
}
}else
if
(mResvKeyState == MotionEvent.ACTION_UP){
updateResvKeyIcon(mResvKeyState, mResvKeyCode);
mResvKeyCode = -1
;
mResvKeyState = -1
;
}else
{
Log.d(TAG, "state machine error! Never be here!"
);
}
}
return
true
;
}
@Override public boolean onTouchEvent(MotionEvent event) { if(mService.mExpanded==true || mService.mTracking==true){ if (event.getAction() != MotionEvent.ACTION_DOWN) { mService.interceptTouchEvent(event); } return true; } if(mResvKeyState == -1) // remembered key state, no reserve { switch(getResvKeyArea(event)){ case RESV_KEY_HOME: case RESV_KEY_BACK: case RESV_KEY_MENU: { mResvKeyState = event.getAction(); mResvKeyCode = getResvKeyArea(event); updateResvKeyIcon(mResvKeyState, mResvKeyCode); } break; default: if (event.getAction() != MotionEvent.ACTION_DOWN) { mService.interceptTouchEvent(event); } } }else{ mResvKeyState = event.getAction(); // new state if(mResvKeyState == MotionEvent.ACTION_MOVE){ if(mResvKeyCode != getResvKeyArea(event)){ /* out of bound, resume the icon */ updateResvKeyIcon(MotionEvent.ACTION_UP, mResvKeyCode); mResvKeyCode = -1; mResvKeyState = -1; } }else if(mResvKeyState == MotionEvent.ACTION_UP){ updateResvKeyIcon(mResvKeyState, mResvKeyCode); mResvKeyCode = -1; mResvKeyState = -1; }else{ Log.d(TAG, "state machine error! Never be here!"); } } return true; }
里面用到的两个private方法简单实现如下:
view plain
copy to clipboard
?
private
int
getResvKeyArea(MotionEvent
event
)
{
if
( (
event
.getX() <= mHomeIcon.getRight())
&& (event
.getY() <=
this
.getHeight()) ){
return
RESV_KEY_HOME;
}
else
if
( (
event
.getX() >= mBackIcon.getLeft())
&& (event
.getY() <=
this
.getHeight()) ){
return
RESV_KEY_BACK;
}
else
if
( (
event
.getX() >= mMenuIcon.getLeft())
&& (event
.getY() <=
this
.getHeight()) ){
return
RESV_KEY_MENU;
}else
return
-1;
}
private
int
updateResvKeyIcon(
int
state,
int
key)
{
if
(key == RESV_KEY_BACK){
if
(state == MotionEvent.ACTION_UP){
mBackIcon.setImageResource(com.android.internal
.R.drawable.stat_back);
}else
if
(state == MotionEvent.ACTION_DOWN){
mBackIcon.setImageResource(com.android.internal
.R.drawable.stat_back_pressed);
}
}else
if
(key == RESV_KEY_HOME){
if
(state == MotionEvent.ACTION_UP){
mHomeIcon.setImageResource(com.android.internal
.R.drawable.stat_home);
}else
if
(state == MotionEvent.ACTION_DOWN){
mHomeIcon.setImageResource(com.android.internal
.R.drawable.stat_home_pressed);
}
}else
if
(key == RESV_KEY_MENU){
if
(state == MotionEvent.ACTION_UP){
mMenuIcon.setImageResource(com.android.internal
.R.drawable.stat_menu);
}else
if
(state == MotionEvent.ACTION_DOWN){
mMenuIcon.setImageResource(com.android.internal
.R.drawable.stat_menu_pressed);
}
}
return
0;
}
private int getResvKeyArea(MotionEvent event) { if( (event.getX() <= mHomeIcon.getRight()) && (event.getY() <= this.getHeight()) ){ return RESV_KEY_HOME; } else if( (event.getX() >= mBackIcon.getLeft()) && (event.getY() <= this.getHeight()) ){ return RESV_KEY_BACK; } else if( (event.getX() >= mMenuIcon.getLeft()) && (event.getY() <= this.getHeight()) ){ return RESV_KEY_MENU; }else return -1; } private int updateResvKeyIcon(int state, int key) { if(key == RESV_KEY_BACK){ if(state == MotionEvent.ACTION_UP){ mBackIcon.setImageResource(com.android.internal.R.drawable.stat_back); }else if(state == MotionEvent.ACTION_DOWN){ mBackIcon.setImageResource(com.android.internal.R.drawable.stat_back_pressed); } }else if(key == RESV_KEY_HOME){ if(state == MotionEvent.ACTION_UP){ mHomeIcon.setImageResource(com.android.internal.R.drawable.stat_home); }else if(state == MotionEvent.ACTION_DOWN){ mHomeIcon.setImageResource(com.android.internal.R.drawable.stat_home_pressed); } }else if(key == RESV_KEY_MENU){ if(state == MotionEvent.ACTION_UP){ mMenuIcon.setImageResource(com.android.internal.R.drawable.stat_menu); }else if(state == MotionEvent.ACTION_DOWN){ mMenuIcon.setImageResource(com.android.internal.R.drawable.stat_menu_pressed); } } return 0; }
同时,我不想再在按下这些icon的时候,触发下拉动作,我也改了onInterceptTouchEvent函数:
view plain
copy to clipboard
?
@Override
public
boolean
onInterceptTouchEvent(MotionEvent event) {
if
( (event.getX() > mHomeIcon.getRight())
&& (event.getX() < mMenuIcon.getLeft())){
return
mService.interceptTouchEvent(event)
? true
:
super
.onInterceptTouchEvent(event);
}
return
false
;
}
@Override public boolean onInterceptTouchEvent(MotionEvent event) { if( (event.getX() > mHomeIcon.getRight()) && (event.getX() < mMenuIcon.getLeft())){ return mService.interceptTouchEvent(event) ? true : super.onInterceptTouchEvent(event); } return false; }
再编译一下,看一下结果
:
)
是不是能动了?
三,添加相应事件
1. 添加新的intent
首先是新增一条intent
,
在
framework/base/core/java/android/content/intent.java
中增加
view plain
copy to clipboard
?
@SdkConstant
(SdkConstantType.BROADCAST_INTENT_ACTION)
public
static
final
String ACTION_ICONKEY_CHANGED =
"android.intent.action.ICONKEY_CHANGED"
;
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_ICONKEY_CHANGED = "android.intent.action.ICONKEY_CHANGED";
2. 发送intent
在StatusBarView.java的OnKeyEvent中,松开按键的分支else if(mResvKeyState == MotionEvent.ACTION_UP)操作中加入发送intent的动作:view plain
copy to clipboard
?
Intent intent =
new
Intent(Intent.ACTION_ICONKEY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra("keycode"
, mResvKeyCode);
mService.sendIntent(intent);
Intent intent = new Intent(Intent.ACTION_ICONKEY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra("keycode", mResvKeyCode); mService.sendIntent(intent);
这个intent是只有注册的接收者才能接收。
这里,我们是通过StatusBarService来发送这个intent的。
在StatusBarService.java中新增一个方法:
view plain
copy to clipboard
?
void
sendIntent(Intent intent)
{
mContext.sendBroadcast(intent);
}
void sendIntent(Intent intent) { mContext.sendBroadcast(intent); }
3.接收并处理intent
这个就要修改StatusBarPolicy.java了首先,在构造函数中加入Intent的filter,注册号这个intent的receiver。
filter.addAction(Intent.ACTION_ICONKEY_CHANGED);
然后再private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() 加入Intent的receiver动作;
view plain
copy to clipboard
?
else
if
(action.equals(Intent.ACTION_ICONKEY_CHANGED)) {
G, "Received ACTION_ICONKEY_CHANGED"
);
updateIconKeyAction(intent);
}
else if (action.equals(Intent.ACTION_ICONKEY_CHANGED)) { Log.d(TAG, "Received ACTION_ICONKEY_CHANGED"); updateIconKeyAction(intent); }
方法updateIconKeyAction的定义如下:
view plain
copy to clipboard
?
private
final
void
updateIconKeyAction(Intent intent){
int
keycode = intent.getIntExtra(
"keycode"
, -
1
);
if
(keycode != -
1
){
long
now = SystemClock.uptimeMillis();
try
{
KeyEvent down = new
KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode,
0
);
KeyEvent up = new
KeyEvent(now, now, KeyEvent.ACTION_UP, keycode,
0
);
(IWindowManager.Stub
.asInterface(ServiceManager.getService("window"
)))
.injectKeyEvent(down, false
);
(IWindowManager.Stub
.asInterface(ServiceManager.getService("window"
)))
.injectKeyEvent(up, false
);
} catch
(RemoteException e) {
Log.i("Input"
,
"DeadOjbectException"
);
}
}
}
private final void updateIconKeyAction(Intent intent){ int keycode = intent.getIntExtra("keycode", -1); if(keycode != -1){ long now = SystemClock.uptimeMillis(); try { KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0); KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0); (IWindowManager.Stub .asInterface(ServiceManager.getService("window"))) .injectKeyEvent(down, false); (IWindowManager.Stub .asInterface(ServiceManager.getService("window"))) .injectKeyEvent(up, false); } catch (RemoteException e) { Log.i("Input", "DeadOjbectException"); } } }
这样,基本上就完成了。
编译一下, 由于新增了一个intent,因此要先make update-api,
view plain
copy to clipboard
?
~/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
另外,如果不是做phone,也可以在StatusBarPolicy.java中将所有phone相关的处理都删掉。
相关文章推荐
- 在android的状态栏(statusbar)中增加menu,home和back快捷键的方法
- 在android的状态栏(statusbar)中增加menu,home和back快捷键的方法
- 在android的状态栏(statusbar)中增加menu,home和back快捷键的方法
- (转)在android的状态栏(statusbar)中增加menu,home和back快捷键的方法
- 在android的状态栏(statusbar)中增加menu,home和back快捷键的方法
- 在Android的状态栏(statusbar)中增加menu,home和back快捷键的方法
- 在android的状态栏(statusbar)中增加menu,home和back快捷键的方法
- 在android的状态栏(statusbar)中增加menu,home和back快捷键的方法
- 在android的状态栏(statusbar)中增加menu,home和back快捷键的方法
- 在android的状态栏中增加menu,home和back快捷键的方法
- 在Android 2.3状态栏中增加menu,home和back快捷键的方法
- 在Android 2.3状态栏中添加menu,home和back快捷键的方法
- 在Android 2.3状态栏中添加menu,home和back快捷键的方法
- 在Android 2.3状态栏中添加menu,home和back快捷键的方法
- 【三星 I9100 在android的状态栏(statusbar)中增加快捷键的方法 】
- Android 2.3状态栏中添加menu,home和back快捷键
- 向android 的状态栏中加入快捷按钮(home,back,menu等等)的方法(续)
- 【摘录】Android 2.3状态栏中添加menu,home和back快捷键
- How to add buttons (Home, Back, Menu) on Android statusBar
- 【转】Android statusBar添加back,home,menu按钮