`

在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单独进行处理。

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

在StatusBarService.java中添加sendIntent2方法

1voidsendIntent2(Intentintent)
2{
3mContext.startActivity(intent);
4}

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

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

分别是

animation_home.xml:

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

animation_back.xml:

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

animation_menu.xml:

1<?xmlversion="1.0"encoding="utf-8"?>
2<animation-listxmlns:android="http://schemas.android.com/apk/res/android"
3android:oneshot="true">
4<item
5android:duration="80"
6android:drawable="@drawable/stat_menu">
7</item>
8<item
9android:duration="80"
10android:drawable="@drawable/stat_menu_pressed">
11</item>
12<item
13android:duration="80"
14android: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<?xmlversion="1.0"encoding="utf-8"?>
2<!--android:background="@drawable/status_bar_closed_default_background"-->
3<com.android.server.status.StatusBarViewxmlns:android="http://schemas.android.com/apk/res/android"
4android:background="@drawable/statusbar_background"
5android:orientation="vertical"
6android:focusable="true"
7android:descendantFocusability="afterDescendants"
8>
9
10<LinearLayoutandroid:id="@+id/icons"
11android:layout_width="fill_parent"
12android:layout_height="fill_parent"
13android:orientation="horizontal">
14<!--Ethan.zhao:StartAddhomebuttononstatus_bar-->
15<ImageView
16android:id="@+id/status_home"
17android:layout_width="wrap_content"
18android:layout_height="wrap_content"
19android:layout_gravity="top"
20android:background="@layout/animation_home"
21/>
22<!--Ethan.zhao:StartAddhomebuttononstatus_bar-->
23
24<com.android.server.status.IconMergerandroid:id="@+id/notificationIcons"
25android:layout_width="0dip"
26android:layout_weight="1"
27android:layout_height="fill_parent"
28android:layout_alignParentLeft="true"
29android:paddingLeft="6dip"
30android:gravity="center_vertical"
31android:orientation="horizontal"/>
32
33<LinearLayoutandroid:id="@+id/statusIcons"
34android:layout_width="wrap_content"
35android:layout_height="fill_parent"
36android:layout_alignParentRight="true"
37android:paddingRight="6dip"
38android:gravity="center_vertical"
39android:orientation="horizontal"/>
40<!--Ethan.zhao:StartAddmenu/backbuttononstatus_bar-->
41<ImageView
42android:id="@+id/status_menu"
43android:layout_width="wrap_content"
44android:layout_height="wrap_content"
45android:layout_gravity="top"
46android:background="@layout/animation_menu"
47/>
48
49<ImageView
50android:id="@+id/status_back"
51android:layout_width="wrap_content"
52android:layout_height="wrap_content"
53android:layout_gravity="top"
54android:background="@layout/animation_back"
55/>
56<!--Ethan.zhao:EndAddthreebuttononstatus_bar-->
57</LinearLayout>
58<LinearLayoutandroid:id="@+id/ticker"
59android:layout_width="fill_parent"
60android:layout_height="fill_parent"
61android:paddingLeft="6dip"
62android:animationCache="false"
63android:orientation="horizontal">
64<ImageSwitcherandroid:id="@+id/tickerIcon"
65android:layout_width="wrap_content"
66android:layout_height="fill_parent"
67android:layout_marginRight="8dip"
68>
69<com.android.server.status.AnimatedImageView
70android:layout_width="25dip"
71android:layout_height="25dip"
72/>
73<com.android.server.status.AnimatedImageView
74android:layout_width="25dip"
75android:layout_height="25dip"
76/>
77</ImageSwitcher>
78<com.android.server.status.TickerViewandroid:id="@+id/tickerText"
79android:layout_width="0dip"
80android:layout_weight="1"
81android:layout_height="wrap_content"
82android:paddingTop="2dip"
83android:paddingRight="10dip">
84<TextView
85android:layout_width="fill_parent"
86android:layout_height="wrap_content"
87android:singleLine="true"
88android:textColor="#ff000000"/>
89<TextView
90android:layout_width="fill_parent"
91android:layout_height="wrap_content"
92android:singleLine="true"
93android:textColor="#ff000000"/>
94</com.android.server.status.TickerView>
95</LinearLayout>
96
97<com.android.server.status.DateViewandroid:id="@+id/date"
98android:layout_width="wrap_content"
99android:layout_height="fill_parent"
100android:singleLine="true"
101android:textSize="16sp"
102android:textStyle="bold"
103android:gravity="center_vertical|left"
104android:paddingLeft="6px"
105android:paddingRight="6px"
106android:textColor="?android:attr/textColorPrimaryInverse"
107android:background="@drawable/statusbar_background"
108/>
109</com.android.server.status.StatusBarView>

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

添加三个AnimationDrawable:

1AnimationDrawablemHomeAnimation;
2AnimationDrawablemBackAnimation;
3AnimationDrawablemMenuAnimation;

在onFinishInflate()方法中

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

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

1privateintupdateResvKeyIcon(intkey)
2{
3if(key==RESV_KEY_BACK)
4{
5mBackAnimation.run();
6}
7elseif(key==RESV_KEY_HOME)
8{
9mHomeAnimation.run();
10}
11elseif(key==RESV_KEY_MENU)
12{
13mMenuAnimation.run();
14}
15return0;
16}

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

1if(mResvKeyState==-1)//rememberedkeystate,noreserve
2{
3switch(getResvKeyArea(event)){
4caseRESV_KEY_HOME:
5caseRESV_KEY_BACK:
6caseRESV_KEY_MENU:
7{
8mResvKeyState=event.getAction();
9mResvKeyCode=getResvKeyArea(event);
10if(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.<?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_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.<?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_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.voidsendIntent(Intentintent)
2.{
3.mContext.sendBroadcast(intent);
4.}
5.privatevoidsendKeyIntent(intkeycode){
6.Intentintent=newIntent(Intent.ACTION_ICONKEY_CHANGED);
7.intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
8.intent.putExtra("keycode",keycode);
9.sendIntent(intent);
10.}
11.
12.privateOnTouchListenerhomeOnTouch=newOnTouchListener(){
13.//@Override
14.publicbooleanonTouch(Viewv,MotionEventevent)
15.{
16.//TODOAuto-generatedmethodstub
17.switch(event.getAction()){
18.caseMotionEvent.ACTION_UP:
19.{
20.sendKeyIntent(RESV_KEY_HOME);
21.}
22.break;
23.}
24.returnfalse;
25.}
26.};
27.
28.privateOnTouchListenerbackOnTouch=newOnTouchListener(){
29.//@Override
30.publicbooleanonTouch(Viewv,MotionEventevent)
31.{
32.//TODOAuto-generatedmethodstub
33.switch(event.getAction()){
34.caseMotionEvent.ACTION_UP:
35.{
36.sendKeyIntent(RESV_KEY_BACK);
37.}
38.break;
39.}
40.returnfalse;
41.}
42.};
43.
44.privateOnTouchListenermenuOnTouch=newOnTouchListener(){
45.//@Override
46.publicbooleanonTouch(Viewv,MotionEventevent)
47.{
48.//TODOAuto-generatedmethodstub
49.switch(event.getAction()){
50.caseMotionEvent.ACTION_UP:
51.{
52.sendKeyIntent(RESV_KEY_MENU);
53.}
54.break;
55.}
56.returnfalse;
57.}
58.};


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

1.publicbooleanonInterceptTouchEvent(MotionEventevent){
2.if((event.getX()>mHomeBtn.getRight())
3.&&(event.getX()<mMenuBtn.getLeft())){
4.returnmService.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.privatefinalvoidupdateIconKeyAction(Intentintent){
2.intkeycode=intent.getIntExtra("keycode",-1);
3.IWindowManagerwm=IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
4.
5.if(keycode!=-1){
6.longnow=SystemClock.uptimeMillis();
7.
8.KeyEventdown=newKeyEvent(now,now,KeyEvent.ACTION_DOWN,keycode,0);
9.KeyEventup=newKeyEvent(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.publicvoidhiddenHotIcons(){
2.mHomeBtn.setVisibility(View.INVISIBLE);
3.mBackBtn.setVisibility(View.INVISIBLE);
4.mMenuBtn.setVisibility(View.INVISIBLE);
5.}
6.
7.publicvoidshowHotIcons(){
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开发板上的效果如下图


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics