Android 2.3 修改 statusbar

Android 2.2 和android 2.3 在源碼結構上有一些變化:tatusbar 的位置的變化,2.3中 statusbar 的源碼在 frameworks/base/packages/SystemUI中。

修改statusbar的背景,frameworks/base/packages/SystemUI/res/drawable-mdpi,替換       statusbar_background.9.png

調整statusbar的高度,frameworks/base/core/res/res/values/dimens.xml 中,修改 <dimen name="status_bar_height">25dip</dimen> 的值

調整statusbar中的日期和時鐘的字體:frameworks/base/packages/SystemUI/res/layout/status_bar.xml 中,會有如下的代碼 <com.Android.systemui.statusbar.Clock 定義時鐘的樣式,可以添加字體的屬性 如: android:textSize等;<com.android.systemui.statusbar.DateView  定義的是日期的樣式,可以添加字體的屬性 如: android:textSize等。

去掉statusbar中的圖標,在平板開發的過程中,有一些手機的功能可能在平板上用不到,如3G功能,但是怎麼樣把statusbar中的3G的圖標去掉呢?在 framework/base/packages/SystemUI/src/com/Android/systemui/statusbar/StatusBarPolicy.java 中會有下面的代碼 mService.setIcon("phone_signal", mPhoneSignalIconId, 0);  這裏是設置手機信號的圖標,去掉3G信號圖標只需將這個文件中的 這句話註釋即可。相應的也可以修改其他的圖標。

修改完之後可以直接編譯SystemUI,然後push 到/system/app 中,即可看到效果。

編譯 SystemUI: 在Android根目錄執行 source build/envsetup.sh ,然後在根目錄執行 mm SystemUI ,最後會在 out/target/product/generic/system/app 中生成一個SystemUI.apk,

adb push SystemUI.apk    /system/app;

statusbar是一種服務,需要啓動satusbar服務:Android 啓動服務 命令: adb shell am start -n com.android.systemui/com.android.systemui.statusbar.StatusBarService,即可看到效果。

關於Android啓動Activity: adb shell am start -n 包名/包名.Activity名;啓動服務:adb shell am start -n 包名/包名.服務名

##########################################################


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/core/res/res/drawable下創建三個imageButton的xml文件:

xml_stat_home.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?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.server.status.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="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal">
 
    <ImageButton android:id="@+id/go_home"
        android:layout_width="36px"
        android:layout_height="36px"
        android:layout_marginRight="15px"
        android:layout_marginLeft="10px"
        android:layout_marginTop="5px"
        android:clickable="true" 
        android:background="@drawable/xml_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"/>    
 
      <ImageButton android:id="@+id/pop_menu"
        android:layout_width="36px"
        android:layout_height="36px"
        android:layout_marginRight="15px"
        android:layout_marginLeft="10px"
        android:layout_marginTop="5px"
        android:clickable="true" 
        android:background="@drawable/xml_stat_menu"
        />        
     <ImageButton android:id="@+id/go_back"
        android:layout_width="36px"
        android:layout_height="36px"
        android:layout_marginRight="15px"
        android:layout_marginLeft="10px"
        android:layout_marginTop="5px"
        android:clickable="true" 
        android:background="@drawable/xml_stat_back"
        />         
    </LinearLayout>
 
    <LinearLayout android:id="@+id/ticker"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:paddingLeft="6dip"
        android:animationCache="false"
        android:orientation="horizontal" >
        <ImageSwitcher android:id="@+id/tickerIcon"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_marginRight="8dip"
            >
            <com.android.server.status.AnimatedImageView
                android:layout_width="36dip"
                android:layout_height="36dip"
                />
            <com.android.server.status.AnimatedImageView
                android:layout_width="36dip"
                android:layout_height="36dip"
                />
        </ImageSwitcher>
        <com.android.server.status.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:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:singleLine="true"
                android:textColor="#ff000000" />
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:singleLine="true"
                android:textColor="#ff000000" />
        </com.android.server.status.TickerView>
    </LinearLayout>
 
    <com.android.server.status.DateView android:id="@+id/date"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:singleLine="true"
        android:textSize="20sp"
        android:textStyle="bold"
        android:gravity="center_vertical|left"
        android:paddingLeft="6px"
        android:paddingRight="6px"
        android:textColor="?android:attr/textColorPrimaryInverse"
        android:background="@drawable/statusbar_background"
        />
</com.android.server.status.StatusBarView>

如上篇,修改statusbar的高度,編譯一下,即可看到效果。

2。 添加按鈕的動作效果
在statusBarView.java中,活的button的handler

類中新增加三個成員:

1
2
3
 ImageButton mHomeBtn;
 ImageButton mBackBtn;
 ImageButton mMenuBtn;

增加三個常量:

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中,獲取幾個button 的handler,並設置touch事件,添加如下代碼:

1
2
3
4
5
6
7
		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);

各button的touch事件添加如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
	private void sendKeyIntent(int keycode){
		Intent intent = new Intent(Intent.ACTION_ICONKEY_CHANGED);
	    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
		intent.putExtra("keycode",   keycode);
		mService.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;   
        } 
	};

也就是簡單的廣播一個intent消息給statusBarPolicy處理。

爲防止點擊statusBar上的按鈕, 觸發標題欄的expend事件, 修改一下函數onInterceptTouchEvent,點擊到不屬於button區域時才允許解析Motion的event:

1
2
3
4
5
6
7
8
9
10
11
    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);
    }
}

修改StatusBarService.java,發送Intent消息需要content,這個目前只能在StatusBarService中添加一個方法:

1
2
3
4
void sendIntent(Intent intent)
    {
     mContext.sendBroadcast(intent);
    }

要發送intent,需要自己添加Intent:

在framework/base/core/java/android/content/intent.java中增加

1
2
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)   
public static final String ACTION_ICONKEY_CHANGED = "android.intent.action.ICONKEY_CHANGED";

接收並處理intent, 如前篇:

接收並處理intent

這個就要修改StatusBarPolicy.java了

首先,在構造函數中加入Intent的filter,註冊號這個intent的receiver。

1
filter.addAction(Intent.ACTION_ICONKEY_CHANGED);

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

1
2
3
4
else if (action.equals(Intent.ACTION_ICONKEY_CHANGED)) {
				Log.d(TAG, "Received ACTION_ICONKEY_CHANGED");
                updateIconKeyAction(intent);
            }

及處理函數:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
	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");
	        }
		}
	}

3. StatusBar通知欄屏蔽按鈕

當拉出expand的通知欄時,按鈕的響應非常慢,這時最好將按鈕給屏蔽掉,我們在 statusBarView.java中增加兩個方法:

1
2
3
4
5
6
7
8
9
10
11
	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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    void performExpand() {
        if (SPEW) Log.d(TAG, "performExpand: mExpanded=" + mExpanded);
        if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
            return ;
        }
        if (mExpanded) {
            return;
        }
 
        // It seems strange to sometimes not expand...
        if (false) {
            synchronized (mNotificationData) {
                if (mNotificationData.size() == 0) {
                    return;
                }
            }
        }
 
        mExpanded = true;
        makeExpandedVisible();
		mStatusBarView.hiddenHotIcons(); // Changed!!!
        updateExpandedViewPos(EXPANDED_FULL_OPEN);
 
        if (false) postStartTracing();
    }
 
    void performCollapse() {
        if (SPEW) Log.d(TAG, "performCollapse: mExpanded=" + mExpanded
                + " mExpandedVisible=" + mExpandedVisible);
 
        if (!mExpandedVisible) {
            return;
        }
        mExpandedVisible = false;
        panelSlightlyVisible(false);
        mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
        mExpandedDialog.getWindow().setAttributes(mExpandedParams);
        mTrackingView.setVisibility(View.GONE);
 
		mStatusBarView.showHotIcons(); // Changed!!!!
        if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
            setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
        }
        setDateViewVisibility(false, com.android.internal.R.anim.fade_out);
 
        if (!mExpanded) {
            return;
        }
        mExpanded = false;
    }

原文鏈接:http://blog.csdn.net/freshui/archive/2010/11/24/6033377.aspx



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章