安卓開發之設定狀態列的顏色
要求:實現設定狀態列的顏色需要至少4.4.2(API 19以上)。在這個版本一下,沒有任何的API可以實現這樣的功能。具體實現方式如下:
一、Android 4.4.2
新增了一個特性,就是可以設定系統狀態為半透明。設定方法有兩種:
1、通過style新增屬性:<item name="android:windowTranslucentStatus">true</item>
2、通過JAVA程式碼設定
Window window=activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
系統設定成半透明之後,我們就可以通過網Window視窗的decoView新增一個View,讓它大小與系統狀態列一樣,然後設定這個View的背景,這樣就實現了改變狀態列的目的了。程式碼如下:
ViewGroup decorViewGroup =(ViewGroup)window.getDecorView();
View statusBarView=new View(window.getContext());
int statusBarHeight=getStatusBarHeight(window.getContext());
FrameLayout.LayoutParams params=new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,statusBarHeight);
params.gravity=Gravity.TOP;
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(color);
decorViewGroup.addView(statusBarView);
其中獲取狀態列的高度的方法程式碼為:
private static int getStatusBarHeight(Context context){
int statusBarHeight=0;
Resource res=context.getResource();
int resourceId=res.getIdentifier("status_bar_height","dimen","android");
if(resourceId>0){
statusBarHeight=res.getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}
然後我們在Acticity的Oncreate方法中使用以上程式碼就行了。
但是在使用的時候,會發現Activity的佈局內容頂到了狀態列上去,被狀態列及ActionBar所覆蓋。解決方法很簡單,只要在佈局檔案的根元素設定一下屬性:android:fitsSystemWindows="true"
它的意思是使這個layout內嵌,也就是會為狀態列等留出空間,於是我們的佈局就回復正常了。
但是問題來了,加入有十幾個Activity,每一個都要修改它的佈局檔案,那多麻煩啊。解決辦法是在Application主題中配置這個屬性。但是衍生出來的一個問題就是Toast顯示不正常了,文字會超出黑色背景之外。解決辦法是,在setContentView()之後,加入一下程式碼:
ViewGroup mContentView =(ViewGroup)window.findViewById(Window.ID_ANDROID_CONTENT);
View mChildView=mContentView.getChildAt(0);
if(mChildView!=NULL){
//注意不是設定ContentView的FitsSystemWindows,而是設定ContentView的第一個子View,預留出系統View的空間。
mChildView.setFitsSystemWindows(fitSystemWindows);
}
二、Android 5.0.1
在這個版本中又增加了一些新的特性,包括一個重要的方法:window.setStatusColor(Color);
直接設定狀態列的顏色,但是想要生效,必須設定一個FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS屬性,並且確保FLAG_TANSLUCENT_STATUS不被設定。
Window window=activity.getWindow();
//取消設定透明狀態列,使ContentView內容不再覆蓋狀態列
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//需要設定這個flag才能呼叫setStatusBarClor來設定狀態列的顏色
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUND);
//設定狀態列的顏色
window.setStatusBarColor(color);
三、Android 6.0
本版本設定狀態列的顏色與上面的一致,程式碼跟上面一樣
//取消設定透明狀態列,使ContentView內容不再覆蓋狀態列
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//需要設定這個flag才能呼叫setStatusBarClor來設定狀態列的顏色
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUND);
//設定狀態列的顏色
window.setStatusBarColor(color);
但是在這裡,如果我的狀態列被設定成白色的話,上面同樣白色的系統狀態就看不到了。不過6.0的API新增了一個屬性來解決這樣的問題:如果我們設定的狀態列的顏色接近於白色的話,可以在主題中新增以下屬性:
<item name="android:windowLightStatusBar">true</tem>
當然也可以通過JAVA程式碼來實現:
View decor =window.getDecorView();
int ui=decor.getSystemUiVisibility();
if(lightStatusBar){
ui |=View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}else {
ui &=View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
decor.setSystemUiVisibility(ui);
四、快速實現
在專案的build.gradle中宣告以下依賴
compile 'com.githang:status-bar-compat:0.3'
在Activity中新增下面的程式碼,在setContentView()被呼叫之後
StatusBarCompat.setStatusBarColor(this,color,lightStatusBar);
不用考慮版本,不用考慮fitsSystemWindows問題,不用考慮狀態列被設定成白色後看不到系統狀態的問題,並且相容MIUI及Flyme。