在android的状态栏(statusbar)中增加menu,home和back快捷键的方法

http://blog.csdn.net/caszhao/article/details/5986743

在状态栏上添加Menu,Back,Home三个按钮的方法,在下文有良好的阐述。详见:

《在android的状态栏(statusbar)中增加menu,home和back快捷键的方法》http://blog.csdn.net/freshui/archive/2010/07/15/5738115.aspx

在使用过程中,存在两个问题:

  • HOME键在我的机器上无效
  • 连击按钮时,由于有时Intent未响应,导致弹起操作未响应直接诶被WindowsManager抛掉。这样就出现了虽然手已离开屏幕,但按钮出现高亮的状态。

1、对于第一个问题,我的方法是把home键单独进行处理,向launcher发送一个启动activity的Intent,这样可以直接回到桌面上。在原方法的基础上,对Home单独进行处理。

1 if (RESV_KEY_HOME = = mResvKeyCode)
2 {
3 Log . d(TAG, "HOMEbuttonIntent!" );
4 Intent intent = new Intent(Intent . ACTION_MAIN);
5 intent . setFlags(Intent . FLAG_ACTIVITY_NEW_TASK);
6 intent . addCategory(Intent . CATEGORY_HOME);
7 mService . sendIntent2(intent);
8 }
9 else
10 {
11 Log . d(TAG, "othertwobuttonsIntent!" );
12 Intent intent = new Intent(Intent . ACTION_ICONKEY_CHANGED);
13 intent . addFlags(Intent . FLAG_RECEIVER_REGISTERED_ONLY);
14 intent . putExtra( "keycode" , mResvKeyCode);
15 mService . sendIntent(intent);
16 }

在StatusBarService.java中添加sendIntent2方法

1 void sendIntent2(Intent intent)
2 {
3 mContext . startActivity(intent);
4 }

2、第二个问题的修正思想是使用Animation逐帧动画来使得按钮从完成 正常态按下后-变化至高亮态-恢复正常态 这一周期。

a. 先在res/layout(与status_bar.xml同目录)中添加三个animation动画xml配置文件。

分别是

animation_home.xml:

1 < ?xml version = " 1.0 " encoding = " utf-8 " ? >
2 < animation-list xmlns:android = " http://schemas.android.com/apk/res/android "
3 android:oneshot = " true " >
4 < item
5 android:duration = " 80 "
6 android:drawable = " @drawable/stat_home " >
7 < /item >
8 < item
9 android:duration = " 80 "
10 android:drawable = " @drawable/stat_home_pressed " >
11 < /item >
12 < item
13 android:duration = " 80 "
14 android:drawable = " @drawable/stat_home " >
15 < /item >
16 < /animation-list >

animation_back.xml:

1 < ?xml version = " 1.0 " encoding = " utf-8 " ? >
2 < animation-list xmlns:android = " http://schemas.android.com/apk/res/android "
3 android:oneshot = " true " >
4 < item
5 android:duration = " 80 "
6 android:drawable = " @drawable/stat_back " >
7 < /item >
8 < item
9 android:duration = " 80 "
10 android:drawable = " @drawable/stat_back_pressed " >
11 < /item >
12 < item
13 android:duration = " 80 "
14 android:drawable = " @drawable/stat_back " >
15 < /item >
16 < /animation-list >
17
18
19

animation_menu.xml:

1 < ?xml version = " 1.0 " encoding = " utf-8 " ? >
2 < animation-list xmlns:android = " http://schemas.android.com/apk/res/android "
3 android:oneshot = " true " >
4 < item
5 android:duration = " 80 "
6 android:drawable = " @drawable/stat_menu " >
7 < /item >
8 < item
9 android:duration = " 80 "
10 android:drawable = " @drawable/stat_menu_pressed " >
11 < /item >
12 < item
13 android:duration = " 80 "
14 android:drawable = " @drawable/stat_menu " >
15 < /item >
16 < /animation-list >
17
18

这三个xml文件分别对应着 home back menu的动画过程

b . 在res/layout/status_bar.xml中修改Imageview的background指向上述三个xml配置文件:

1 < ?xml version = " 1.0 " encoding = " utf-8 " ? >
2 <!-- android:background="@drawable/status_bar_closed_default_background" -->
3 < com.android.server.status.StatusBarView xmlns:android = " http://schemas.android.com/apk/res/android "
4 android:background = " @drawable/statusbar_background "
5 android:orientation = " vertical "
6 android:focusable = " true "
7 android:descendantFocusability = " afterDescendants "
8 >
9
10 < LinearLayout android:id = " @+id/icons "
11 android:layout _width= " fill_parent "
12 android:layout _height= " fill_parent "
13 android:orientation = " horizontal " >
14 <!-- Ethan.zhao : Start Add home button on status_bar -->
15 < ImageView
16 android:id = " @+id/status_home "
17 android:layout _width= " wrap_content "
18 android:layout _height= " wrap_content "
19 android:layout _gravity= " top "
20 android:background = " @layout/animation_home "
21 / >
22 <!-- Ethan.zhao : Start Add home button on status_bar -->
23
24 < com.android.server.status.IconMerger android:id = " @+id/notificationIcons "
25 android:layout _width= " 0dip "
26 android:layout _weight= " 1 "
27 android:layout _height= " fill_parent "
28 android:layout _alignParentLeft= " true "
29 android:paddingLeft = " 6dip "
30 android:gravity = " center_vertical "
31 android:orientation = " horizontal " / >
32
33 < LinearLayout android:id = " @+id/statusIcons "
34 android:layout _width= " wrap_content "
35 android:layout _height= " fill_parent "
36 android:layout _alignParentRight= " true "
37 android:paddingRight = " 6dip "
38 android:gravity = " center_vertical "
39 android:orientation = " horizontal " / >
40 <!-- Ethan.zhao : Start Add menu/back button on status_bar -->
41 < ImageView
42 android:id = " @+id/status_menu "
43 android:layout _width= " wrap_content "
44 android:layout _height= " wrap_content "
45 android:layout _gravity= " top "
46 android:background = " @layout/animation_menu "
47 / >
48
49 < ImageView
50 android:id = " @+id/status_back "
51 android:layout _width= " wrap_content "
52 android:layout _height= " wrap_content "
53 android:layout _gravity= " top "
54 android:background = " @layout/animation_back "
55 / >
56 <!-- Ethan.zhao : End Add three button on status_bar -->
57 < /LinearLayout >
58 < LinearLayout android:id = " @+id/ticker "
59 android:layout _width= " fill_parent "
60 android:layout _height= " fill_parent "
61 android:paddingLeft = " 6dip "
62 android:animationCache = " false "
63 android:orientation = " horizontal " >
64 < ImageSwitcher android:id = " @+id/tickerIcon "
65 android:layout _width= " wrap_content "
66 android:layout _height= " fill_parent "
67 android:layout _marginRight= " 8dip "
68 >
69 < com.android.server.status.AnimatedImageView
70 android:layout _width= " 25dip "
71 android:layout _height= " 25dip "
72 / >
73 < com.android.server.status.AnimatedImageView
74 android:layout _width= " 25dip "
75 android:layout _height= " 25dip "
76 / >
77 < /ImageSwitcher >
78 < com.android.server.status.TickerView android:id = " @+id/tickerText "
79 android:layout _width= " 0dip "
80 android:layout _weight= " 1 "
81 android:layout _height= " wrap_content "
82 android:paddingTop = " 2dip "
83 android:paddingRight = " 10dip " >
84 < TextView
85 android:layout _width= " fill_parent "
86 android:layout _height= " wrap_content "
87 android:singleLine = " true "
88 android:textColor = " #ff000000 " / >
89 < TextView
90 android:layout _width= " fill_parent "
91 android:layout _height= " wrap_content "
92 android:singleLine = " true "
93 android:textColor = " #ff000000 " / >
94 < /com.android.server.status.TickerView >
95 < /LinearLayout >
96
97 < com.android.server.status.DateView android:id = " @+id/date "
98 android:layout _width= " wrap_content "
99 android:layout _height= " fill_parent "
100 android:singleLine = " true "
101 android:textSize = " 16sp "
102 android:textStyle = " bold "
103 android:gravity = " center_vertical|left "
104 android:paddingLeft = " 6px "
105 android:paddingRight = " 6px "
106 android:textColor = " ?android:attr/textColorPrimaryInverse "
107 android:background = " @drawable/statusbar_background "
108 / >
109 < /com.android.server.status.StatusBarView >

c . 修改StatusBarView.java文件,加入Animation相关代码:

添加三个AnimationDrawable:

1 AnimationDrawable mHomeAnimation;
2 AnimationDrawable mBackAnimation;
3 AnimationDrawable mMenuAnimation;

在onFinishInflate()方法中

1 mHomeAnimation = (AnimationDrawable) mHomeIcon . getBackground();
2 mBackAnimation = (AnimationDrawable) mBackIcon . getBackground();
3 mMenuAnimation = (AnimationDrawable) mMenuIcon . getBackground();

updateResvKeyIcon这个方法,改造成如下这样:

1 private int updateResvKeyIcon( int key)
2 {
3 if (key = = RESV_KEY_BACK)
4 {
5 mBackAnimation . run();
6 }
7 else if (key = = RESV_KEY_HOME)
8 {
9 mHomeAnimation . run();
10 }
11 else if (key = = RESV_KEY_MENU)
12 {
13 mMenuAnimation . run();
14 }
15 return 0 ;
16 }

d. 注释掉所有的updateResvKeyIcon方法,仅保留以下一个,并加上判断语句。

1i f(mResvKeyState = = - 1 ) // remembered key state, no reserve
2 {
3 switch (getResvKeyArea(event)) {
4 case RESV_KEY_HOME :
5 case RESV_KEY_BACK :
6 case RESV_KEY_MENU :
7 {
8 mResvKeyState = event . getAction();
9 mResvKeyCode = getResvKeyArea(event);
10 i f (mResvKeyState = = MotionEvent . ACTION_DOWN) updateResvKeyIcon(mResvKeyCode); // 这句改成这样
附件下载如下:

http://download.csdn.net/source/2807668





http://blog.csdn.net/freshui/article/details/5738115


需要说明的是:刚入手android没几天,对系统还不算很熟悉,这篇文章是基于前一篇转帖做的。只是觉得他的方法有些麻烦,而且改出来的效果也不是我想要的。

由于完全改了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

  1. <LinearLayoutandroid:id="@+id/icons"
  2. android:layout_width="fill_parent"
  3. android:layout_height="fill_parent"
  4. android:orientation="horizontal">
  5. <ImageViewandroid:id="@+id/status_home"
  6. android:layout_width="wrap_content"
  7. android:layout_height="wrap_content"
  8. android:layout_gravity="top"
  9. android:paddingTop="6dip"
  10. android:paddingRight="10dip"
  11. android:paddingLeft="10dip"
  12. android:src="@drawable/stat_home"/>
  13. <com.android.server.status.IconMergerandroid:id="@+id/notificationIcons"
  14. android:layout_width="0dip"
  15. android:layout_weight="1"
  16. android:layout_height="fill_parent"
  17. android:layout_alignParentLeft="true"
  18. android:paddingLeft="6dip"
  19. android:gravity="center_vertical"
  20. android:orientation="horizontal"/>
  21. <LinearLayoutandroid:id="@+id/statusIcons"
  22. android:layout_width="wrap_content"
  23. android:layout_height="fill_parent"
  24. android:layout_alignParentRight="true"
  25. android:paddingRight="6dip"
  26. android:gravity="center_vertical"
  27. android:orientation="horizontal"/>
  28. <ImageViewandroid:id="@+id/status_menu"
  29. android:layout_width="wrap_content"
  30. android:layout_height="wrap_content"
  31. android:layout_gravity="top"
  32. android:paddingTop="6dip"
  33. android:paddingLeft="10dip"
  34. android:paddingRight="10dip"
  35. android:src="@drawable/stat_menu"/>
  36. <ImageViewandroid:id="@+id/status_back"
  37. android:layout_width="wrap_content"
  38. android:layout_height="wrap_content"
  39. android:layout_gravity="top"
  40. android:paddingTop="6dip"
  41. android:paddingRight="10dip"
  42. android:paddingLeft="10dip"
  43. android:src="@drawable/stat_back"/>
  44. /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值,不过我觉得没必要,改了反倒不好看了:)

编译运行一下:

  1. ~/donut$source./env.sh
  2. ~/donut$make–j8
  3. ~/donut$emulator–skinWVGA800

,看状态栏是不是改变了?

二为按钮添加动态效果

添加动态效果,就是触摸按下hilight,松开或者移出后恢复的动作。这一块,我是通过修改frameworks/base/services/java/com/android/server/status/StatusBarView.java实现的。

1.获取statusbar中新增加的icon的handler。

在类中新增加三个成员(这需要import android.widget.ImageView;):

  1. ImageViewmHomeIcon;
  2. ImageViewmBackIcon;
  3. ImageViewmMenuIcon;

同时增加三个常量,表示这些icon对应的键值(这需要import android.view.KeyEvent;)

  1. publicstaticfinalintRESV_KEY_HOME=KeyEvent.KEYCODE_HOME;
  2. publicstaticfinalintRESV_KEY_BACK=KeyEvent.KEYCODE_BACK;
  3. publicstaticfinalintRESV_KEY_MENU=KeyEvent.KEYCODE_MENU;;

在onFinishInflate()中,获得实际的对象:

  1. mHomeIcon=(ImageView)findViewById(R.id.status_home);
  2. mBackIcon=(ImageView)findViewById(R.id.status_back);
  3. mMenuIcon=(ImageView)findViewById(R.id.status_menu);

这三个对象就是我们在status_bar.xml中添加的。

2.添加触摸处理。

首先,应该判断是那个图标被按下,这个我们在StatusBarView.Java的onTouchEvent中来判断。

这里,我做了一个小的按键状态,已方便处理按下、弹起和移出的动作。

首先增加两个状态成员:

  1. intmResvKeyState=-1;//记住的上次按键状态,-1为无状态。
  2. intmResvKeyCode=-1;//记住的上次按键值,-1为无状态。

这样我的onTouchEvent就变成这样了:

  1. @Override
  2. publicbooleanonTouchEvent(MotionEventevent){
  3. if(mService.mExpanded==true||mService.mTracking==true){
  4. if(event.getAction()!=MotionEvent.ACTION_DOWN){
  5. mService.interceptTouchEvent(event);
  6. }
  7. returntrue;
  8. }
  9. if(mResvKeyState==-1)//rememberedkeystate,noreserve
  10. {
  11. switch(getResvKeyArea(event)){
  12. caseRESV_KEY_HOME:
  13. caseRESV_KEY_BACK:
  14. caseRESV_KEY_MENU:
  15. {
  16. mResvKeyState=event.getAction();
  17. mResvKeyCode=getResvKeyArea(event);
  18. updateResvKeyIcon(mResvKeyState,mResvKeyCode);
  19. }
  20. break;
  21. default:
  22. if(event.getAction()!=MotionEvent.ACTION_DOWN){
  23. mService.interceptTouchEvent(event);
  24. }
  25. }
  26. }else{
  27. mResvKeyState=event.getAction();//newstate
  28. if(mResvKeyState==MotionEvent.ACTION_MOVE){
  29. if(mResvKeyCode!=getResvKeyArea(event)){
  30. /*outofbound,resumetheicon*/
  31. updateResvKeyIcon(MotionEvent.ACTION_UP,mResvKeyCode);
  32. mResvKeyCode=-1;
  33. mResvKeyState=-1;
  34. }
  35. }elseif(mResvKeyState==MotionEvent.ACTION_UP){
  36. updateResvKeyIcon(mResvKeyState,mResvKeyCode);
  37. mResvKeyCode=-1;
  38. mResvKeyState=-1;
  39. }else{
  40. Log.d(TAG,"statemachineerror!Neverbehere!");
  41. }
  42. }
  43. returntrue;
  44. }

里面用到的两个private方法简单实现如下:

  1. privateintgetResvKeyArea(MotionEventevent)
  2. {
  3. if((event.getX()<=mHomeIcon.getRight())
  4. &&(event.getY()<=this.getHeight())){
  5. returnRESV_KEY_HOME;
  6. }
  7. elseif((event.getX()>=mBackIcon.getLeft())
  8. &&(event.getY()<=this.getHeight())){
  9. returnRESV_KEY_BACK;
  10. }
  11. elseif((event.getX()>=mMenuIcon.getLeft())
  12. &&(event.getY()<=this.getHeight())){
  13. returnRESV_KEY_MENU;
  14. }else
  15. return-1;
  16. }
  17. privateintupdateResvKeyIcon(intstate,intkey)
  18. {
  19. if(key==RESV_KEY_BACK){
  20. if(state==MotionEvent.ACTION_UP){
  21. mBackIcon.setImageResource(com.android.internal.R.drawable.stat_back);
  22. }elseif(state==MotionEvent.ACTION_DOWN){
  23. mBackIcon.setImageResource(com.android.internal.R.drawable.stat_back_pressed);
  24. }
  25. }elseif(key==RESV_KEY_HOME){
  26. if(state==MotionEvent.ACTION_UP){
  27. mHomeIcon.setImageResource(com.android.internal.R.drawable.stat_home);
  28. }elseif(state==MotionEvent.ACTION_DOWN){
  29. mHomeIcon.setImageResource(com.android.internal.R.drawable.stat_home_pressed);
  30. }
  31. }elseif(key==RESV_KEY_MENU){
  32. if(state==MotionEvent.ACTION_UP){
  33. mMenuIcon.setImageResource(com.android.internal.R.drawable.stat_menu);
  34. }elseif(state==MotionEvent.ACTION_DOWN){
  35. mMenuIcon.setImageResource(com.android.internal.R.drawable.stat_menu_pressed);
  36. }
  37. }
  38. return0;
  39. }

同时,我不想再在按下这些icon的时候,触发下拉动作,我也改了onInterceptTouchEvent函数:

  1. @Override
  2. publicbooleanonInterceptTouchEvent(MotionEventevent){
  3. if((event.getX()>mHomeIcon.getRight())
  4. &&(event.getX()<mMenuIcon.getLeft())){
  5. returnmService.interceptTouchEvent(event)
  6. ?true:super.onInterceptTouchEvent(event);
  7. }
  8. returnfalse;
  9. }

再编译一下,看一下结果:)是不是能动了?

三,添加相应事件

1. 添加新的intent

首先是新增一条intent,在framework/base/core/java/android/content/intent.java中增加

  1. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  2. publicstaticfinalStringACTION_ICONKEY_CHANGED="android.intent.action.ICONKEY_CHANGED";

2. 发送intent

在StatusBarView.java的OnKeyEvent中,松开按键的分支else if(mResvKeyState == MotionEvent.ACTION_UP)操作中加入发送intent的动作:

  1. Intentintent=newIntent(Intent.ACTION_ICONKEY_CHANGED);
  2. intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
  3. intent.putExtra("keycode",mResvKeyCode);
  4. mService.sendIntent(intent);

这个intent是只有注册的接收者才能接收。

这里,我们是通过StatusBarService来发送这个intent的。

在StatusBarService.java中新增一个方法:

  1. voidsendIntent(Intentintent)
  2. {
  3. mContext.sendBroadcast(intent);
  4. }

3.接收并处理intent

这个就要修改StatusBarPolicy.java了

首先,在构造函数中加入Intent的filter,注册号这个intent的receiver。

filter.addAction(Intent.ACTION_ICONKEY_CHANGED);

然后再private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() 加入Intent的receiver动作;

  1. elseif(action.equals(Intent.ACTION_ICONKEY_CHANGED)){
  2. G,"ReceivedACTION_ICONKEY_CHANGED");
  3. updateIconKeyAction(intent);
  4. }

方法updateIconKeyAction的定义如下:

  1. privatefinalvoidupdateIconKeyAction(Intentintent){
  2. intkeycode=intent.getIntExtra("keycode",-1);
  3. if(keycode!=-1){
  4. longnow=SystemClock.uptimeMillis();
  5. try{
  6. KeyEventdown=newKeyEvent(now,now,KeyEvent.ACTION_DOWN,keycode,0);
  7. KeyEventup=newKeyEvent(now,now,KeyEvent.ACTION_UP,keycode,0);
  8. (IWindowManager.Stub
  9. .asInterface(ServiceManager.getService("window")))
  10. .injectKeyEvent(down,false);
  11. (IWindowManager.Stub
  12. .asInterface(ServiceManager.getService("window")))
  13. .injectKeyEvent(up,false);
  14. }catch(RemoteExceptione){
  15. Log.i("Input","DeadOjbectException");
  16. }
  17. }
  18. }

这样,基本上就完成了。

编译一下, 由于新增了一个intent,因此要先make update-api,

  1. ~/donut$source./env.sh
  2. ~/donut$makeupdate-api
  3. ~/donut$make–j8
  4. ~/donut$emulator–skinWVGA800

另外,如果不是做phone,也可以在StatusBarPolicy.java中将所有phone相关的处理都删掉。



______________________________________________________________________________________________________________

在Android 2.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.<?xmlversion="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 or agreed to in writing, software
14.** distributed under the License is distributed on an "AS IS" BASIS,
15.** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16.** See the License for the specific language 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.android:orientation="vertical"
26.android:focusable="true"
27.android:descendantFocusability="afterDescendants"
28.>
29.
30.<LinearLayout android:id="@+id/icons"
31.android:layout_width="match_parent"
32.android:layout_height="match_parent"
33.android:orientation="horizontal">
34.<com.android.systemui.statusbar.IconMerger android: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.android:orientation="horizontal"/>
42.
43.<LinearLayout android: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.android:orientation="horizontal"/>
50.<ImageButton android: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.<ImageButton android: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.android:orientation="horizontal"
68. android:clickable="true"
69. android:background="@drawable/xml_stat_menu"
70. />
71.<ImageButton android: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.android:orientation="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.<LinearLayout android:id="@+id/ticker"
93.android:layout_width="match_parent"
94.android:layout_height="match_parent"
95.android:paddingLeft="6dip"
96.android:animationCache="false"
97.android:orientation="horizontal" >
98.<ImageSwitcher android: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.TickerView android: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.DateView android: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. ImageButtonmHomeBtn;
2. ImageButtonmBackBtn;
3. ImageButtonmMenuBtn;
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事件,添加如下代码:

1. mHomeBtn =(ImageButton)findViewById(R.id.go_home);
2. mBackBtn =(ImageButton)findViewById(R.id.go_back);
3. mMenuBtn =(ImageButton)findViewById(R.id.pop_menu);
4.
5. mHomeBtn.setOnTouchListener(homeOnTouch);
6. mBackBtn.setOnTouchListener(backOnTouch);
7. mMenuBtn.setOnTouchListener(menuOnTouch);


各button的touch事件添加如下:

1. void sendIntent ( Intent intent )
2. {
3. mContext.sendBroadcast(intent);
4. }
5. privatevoid sendKeyIntent( int keycode){
6. Intentintent= 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 OnTouchListenerhomeOnTouch= new OnTouchListener(){
13. //@Override
14. publicboolean onTouch(Viewv,MotionEventevent)
15. {
16. //TODOAuto-generatedmethodstub
17. switch (event.getAction()){
18. case MotionEvent.ACTION_UP:
19. {
20. sendKeyIntent(RESV_KEY_HOME);
21. }
22. break ;
23. }
24. returnfalse ;
25. }
26. };
27.
28. private OnTouchListenerbackOnTouch= new OnTouchListener(){
29. //@Override
30. publicboolean onTouch(Viewv,MotionEventevent)
31. {
32. //TODOAuto-generatedmethodstub
33. switch (event.getAction()){
34. case MotionEvent.ACTION_UP:
35. {
36. sendKeyIntent(RESV_KEY_BACK);
37. }
38. break ;
39. }
40. returnfalse ;
41. }
42. };
43.
44. private OnTouchListenermenuOnTouch= new OnTouchListener(){
45. //@Override
46. publicboolean onTouch(Viewv,MotionEventevent)
47. {
48. //TODOAuto-generatedmethodstub
49. switch (event.getAction()){
50. case MotionEvent.ACTION_UP:
51. {
52. sendKeyIntent(RESV_KEY_MENU);
53. }
54. break ;
55. }
56. returnfalse ;
57. }
58. };


为防止点击statusBar上的按钮, 触发标题栏的expend事件, 修改一下函数onInterceptTouchEvent,点击到不属于button区域时才允许解析Motion的event:

1. publicboolean onInterceptTouchEvent(MotionEventevent){
2. if ((event.getX()>mHomeBtn.getRight())
3. &&(event.getX()<mMenuBtn.getLeft())){
4. return mService.interceptTouchEvent(event)
5. ? true : super .onInterceptTouchEvent(event);
6. }
7. returnfalse ;
8. //returnmService.interceptTouchEvent(event)
9. //?true:super.onInterceptTouchEvent(event);
10. }
11. }


需要自己添加Intent
打开frameworks/base/core/java/android/content/Intent.java,增加下面的内容,由于我们的使用的API不公开,须加上
/**@hide*/,不然编译会报错

1. /**
2.* @hide
3.*/
4.public static final String ACTION_ICONKEY_CHANGED ="android.intent.action.ICONKEY_CHANGED";
5.


接收并处理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. elseif (action.equals(Intent.ACTION_ICONKEY_CHANGED)){
2. Log.d(TAG, "ReceivedACTION_ICONKEY_CHANGED" );
3. updateIconKeyAction(intent);
4. }


及处理函数:
须导入以下包
import android.view.IWindowManager;
import android.os.SystemClock;
import android.view.KeyEvent;

1. privatefinalvoid updateIconKeyAction(Intentintent){
2. int keycode=intent.getIntExtra( "keycode" ,- 1 );
3. IWindowManagerwm=IWindowManager.Stub.asInterface(ServiceManager.getService( "window" ));
4.
5. if (keycode!=- 1 ){
6. long now=SystemClock.uptimeMillis();
7.
8. KeyEventdown= new KeyEvent(now,now,KeyEvent.ACTION_DOWN,keycode, 0 );
9. KeyEventup= new KeyEvent(now,now,KeyEvent.ACTION_UP,keycode, 0 );
10.
11. try {
12. wm.injectKeyEvent(down, false );
13. } catch (RemoteExceptione){
14. Log.i( "Input" , "DeadOjbectException" );
15. }
16.
17. try {
18. wm.injectKeyEvent(up, false );
19. } catch (RemoteExceptione){
20. Log.i( "Input" , "DeadOjbectException" );
21. }
22. }
23. }


StatusBar通知栏屏蔽按钮
当拉出expand的通知栏时,按钮的响应非常慢,这时最好将按钮给屏蔽掉,我们在 statusBarView.java中增加两个方法:

1. publicvoid hiddenHotIcons(){
2. mHomeBtn.setVisibility(View.INVISIBLE);
3. mBackBtn.setVisibility(View.INVISIBLE);
4. mMenuBtn.setVisibility(View.INVISIBLE);
5. }
6.
7. publicvoid 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.java

1. void performExpand() {
2. if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded);
3. if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
4. return ;
5. }
6. if (mExpanded) {
7. return;
8. }
9. mExpanded = true;
10. makeExpandedVisible();
11.mStatusBarView.hiddenHotIcons();
12. updateExpandedViewPos(EXPANDED_FULL_OPEN);
13. if (false) postStartTracing();
14. }
15. void performCollapse() {
16. if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
17. + " mExpandedVisible=" + mExpandedVisible
18. + " mTicking=" + mTicking);
19.
20. if (!mExpandedVisible) {
21. return;
22. }
23. mExpandedVisible = false;
24. visibilityChanged(false);
25. mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
26. mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
27. mExpandedDialog.getWindow().setAttributes(mExpandedParams);
28. mTrackingView.setVisibility(View.GONE);
29. mExpandedView.setVisibility(View.GONE);
30.
31. mStatusBarView.showHotIcons();
32.
33. if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
34. setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
35. }
36. if (mDateView.getVisibility() == View.VISIBLE) {
37. setDateViewVisibility(false, com.android.internal.R.anim.fade_out);
38. }
39.
40. if (!mExpanded) {
41. return;
42. }
43. mExpanded = false;
44. }

编译工程
#source /opt/android_froyo_smdk/build/envsetup.sh
#export TARGET_PRODUCT=full_smdkv210
#mmm frameworks/base/
把编译生成的相关文件放进SD卡对应的目录即可, 在伟研科技 WY-S5PV210开发板上的效果如下图


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值