一蛮放、概述
關于狀態(tài)欄的討論很多缩抡,我們今天從需求的角度來看一下對于狀態(tài)欄的知識點:
- 不顯示狀態(tài)欄
(4.4)
- 通過
Window
- 通過
DecorView
- 顯示狀態(tài)欄
- 靜態(tài)設置狀態(tài)欄透明
(4.4)
:windowTranslucentStatus
,需要解決重疊問題- 手動設置
padding
fitsSystemWindows
- 手動設置
- 設置狀態(tài)欄顏色
(5.0)
:-
colorPrimaryDark
包颁,style
中指定瞻想。 -
setStatusBarColor
,動態(tài)設定娩嚼。
-
- 設置狀態(tài)欄和根布局的層級關系
(4.4)
:-
SYSTEM_UI_FLAG_VISIBLE
:狀態(tài)欄不覆蓋根布局 -
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
:狀態(tài)欄覆蓋根布局
-
- 動態(tài)設置狀態(tài)欄透明
(5.0)
- 改變狀態(tài)欄圖標顏色
- 官方做法
(6.0)
- 魅族/小米做法
二蘑险、不顯示狀態(tài)欄
不顯示狀態(tài)欄一般用于屏幕可顯示區(qū)域較小的時候,并且要求可見面積較大的情況岳悟,例如視頻佃迄、橫屏等,而不顯示狀態(tài)欄的方法有兩種贵少,下面我們分別介紹一下:
2.1 通過Activity
所屬的Window
public static void setStatusBarVisibleByWindow(Activity activity, boolean visible) {
Window window = activity.getWindow();
if (window != null) {
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
if (visible) {
winParams.flags &= ~bits;
} else {
winParams.flags |= bits;
}
window.setAttributes(winParams);
}
}
2.2 通過DecorView
public static void setStatusBarVisibleByDecorView(Activity activity, boolean visible) {
Window window = activity.getWindow();
if (window != null) {
if (visible) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
} else {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
}
}
}
2.3 小結(jié)
這兩種方法不可以混合使用呵俏,也就是說,不能通過其中一種方法將狀態(tài)欄隱藏滔灶,又利用另一種方法將它顯示出來普碎。
三、顯示狀態(tài)欄
在顯示狀態(tài)欄的情況下录平,我們將需求分為以下三類:
3.1 設置狀態(tài)欄為透明
要求安卓版本大于4.4麻车。
我們可以在style
中指定,然后設置給Activity
或者Application
:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
</style>
當然斗这,也可以通過代碼來指定:
public static void setStatusBarTransparent(Activity activity) {
Window window = activity.getWindow();
if (window != null) {
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
winParams.flags |= bits;
window.setAttributes(winParams);
}
}
解決狀態(tài)欄透明時和根布局重疊的問題
這兩種方法是等效的绪氛,但是它們都存在一個問題,根布局會和狀態(tài)欄重疊涝影,這時候就有兩種解決辦法:
3.1.1 在布局中加上和狀態(tài)欄高度相同的padding
這種方法有一點不好枣察,就是我們需要事先知道狀態(tài)欄的高度是多少,或者動態(tài)地獲取,并動態(tài)設置padding
序目。
3.1.2 fitsSystemWindows
為了解決上面的情況臂痕,我們可以通過fitsSystemWindows
屬性讓系統(tǒng)自動根據(jù)狀態(tài)欄的高度來給我們的布局留下足夠的空間。
- 在根布局的
xml
中配置android:fitsSystemWindows
屬性:
<LinearLayout android:fitsSystemWindows="true">
3.1.3 小結(jié)
需要注意猿涨,使用上面的方法來試狀態(tài)欄透明握童,需要在Activity
的onCreate
之前設置,如果在之后設置叛赚,那么可能會出現(xiàn)意料之外的結(jié)果澡绩,如果想要在代碼當中設置狀態(tài)欄透明,那么建議采用3.2
和3.3
的結(jié)合版本俺附,也就是改變狀態(tài)欄顏色為透明 + 改變布局肥卡,我們分析完下面的兩種之后,再看一下怎么在代碼中設置事镣。
3.2 改變狀態(tài)欄的顏色
在狀態(tài)欄不透明的情況下步鉴,我們可以通過下面的方法來改變狀態(tài)欄的顏色,要求Android
版本大于5.0
:
3.2.1 通過style
設置
其中colorPrimaryDark
就是指定的狀態(tài)欄顏色
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@android:color/holo_green_light</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
這里有一點:如果我們設置了上面的屬性璃哟,并且設置了windowTranslucentStatus
氛琢,即使不將fitSystemWindow
設為true
,也不會使狀態(tài)欄和根布局重疊随闪。
3.2.2 通過代碼動態(tài)設置
public static void setStatusBarColor(Activity activity, int colorId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
if (window != null) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(activity.getResources().getColor(colorId));
}
}
}
3.2.3 小結(jié)
由于上面討論的兩種方法都只能在5.0
以上實現(xiàn)阳似,因此如果我們希望在5.0
以下動態(tài)改變狀態(tài)欄的顏色,那么就只能通過3.1
中的方法铐伴,把狀態(tài)欄設置為透明撮奏,然后在布局中添加一個和狀態(tài)欄高度相同的背景,通過動態(tài)改變這個背景的顏色盛杰,來實現(xiàn)狀態(tài)欄顏色的改變挽荡。
3.3 改變狀態(tài)欄和根布局的關系
其實在上面的兩種方法中,我們也間接地改變了狀態(tài)欄和根布局的關系即供,當然定拟,我們也可以單純改變布局關系,而不對狀態(tài)欄作出任何改變:
public static void setStatusBarOverlay(Activity activity, boolean overlay) {
Window window = activity.getWindow();
if (window != null) {
if (overlay) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
}
}
3.4 動態(tài)設置狀態(tài)欄透明
由于這種方式結(jié)合了3.2
和3.3
逗嫡,因此要求版本要大于5.0
:
public static void setStatusBarTransparentDynamic(Activity activity, boolean overlay) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
if (window != null) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
if (!overlay) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
}
window.setStatusBarColor(Color.TRANSPARENT);
}
}
}
四青自、改變狀態(tài)欄圖標顏色
4.1 官方標準做法
這種方法要求Android
的API
大于6.0
:
public static void setStatusBarItemColor(Activity activity, boolean dark) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Window window = activity.getWindow();
if (window != null) {
final int bits = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
int currentBits = window.getDecorView().getSystemUiVisibility();
if (dark) {
currentBits |= bits;
} else {
currentBits &= ~bits;
}
window.getDecorView().setSystemUiVisibility(currentBits);
}
}
}
4.2 其它廠商做法
五、小結(jié)
5.1
總結(jié)下來驱证,在顯示狀態(tài)欄的情況下延窜,適配范圍最廣的是下面這種方法:
- 通過
DecorView
設置成透明并且重疊的模式(如3.4
) - 在根布局中添加一個布局,這個布局的高度等于狀態(tài)欄的高度抹锄,這樣我們就可以通過控制它的高度和顏色來實現(xiàn)多種組合逆瑞。
- 如果想要改變圖標的顏色荠藤,就只能在
6.0
或者廠商的方法。
5.2
對于狀態(tài)欄的操作主要是兩種:一種是對DecorView
操作获高,另一種是對window
操作哈肖,使用的時候?qū)Τ嗽O置狀態(tài)欄顏色外的操作一定要保持統(tǒng)一,一定不要同時進行這兩種方法來進行相反的操作念秧。舉個例子淤井,如果采用了3.1
中的對window
進行操作使得狀態(tài)欄透明,并通過fitSystemWindows
改變布局摊趾,那么就不要再采用3.3
中DecorView.setSystemUiVisibility()
的方式來改變布局的結(jié)構币狠,最好是成對地出現(xiàn),否則會使得布局出現(xiàn)意料之外的情況砾层。
5.3
最后附上代碼:
public class StatusBarUtils {
public static void setStatusBarVisibleByWindow(Activity activity, boolean visible) {
Window window = activity.getWindow();
if (window != null) {
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
if (visible) {
winParams.flags &= ~bits;
} else {
winParams.flags |= bits;
}
window.setAttributes(winParams);
}
}
public static void setStatusBarVisibleByDecorView(Activity activity, boolean visible) {
Window window = activity.getWindow();
if (window != null) {
if (visible) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
} else {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
}
}
}
public static void setStatusBarTransparent(Activity activity) {
Window window = activity.getWindow();
if (window != null) {
WindowManager.LayoutParams winParams = window.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
winParams.flags |= bits;
window.setAttributes(winParams);
}
}
public static void setStatusBarTransparentDynamic(Activity activity, boolean overlay, boolean transparent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
if (window != null) {
if (transparent) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
if (!overlay) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
}
window.setStatusBarColor(Color.TRANSPARENT);
}
}
}
}
public static void setStatusBarBackgroundColor(Activity activity, int colorId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
if (window != null) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(activity.getResources().getColor(colorId));
}
}
}
public static void setStatusBarOverlay(Activity activity, boolean overlay) {
Window window = activity.getWindow();
if (window != null) {
if (overlay) {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else {
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
}
}
public static void setStatusBarItemColor(Activity activity, boolean dark) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Window window = activity.getWindow();
if (window != null) {
final int bits = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
int currentBits = window.getDecorView().getSystemUiVisibility();
if (dark) {
currentBits |= bits;
} else {
currentBits &= ~bits;
}
window.getDecorView().setSystemUiVisibility(currentBits);
}
}
}
}
更多文章漩绵,歡迎訪問我的 Android 知識梳理系列:
- Android 知識梳理目錄:http://www.reibang.com/p/fd82d18994ce
- 個人主頁:http://lizejun.cn
- 個人知識總結(jié)目錄:http://lizejun.cn/categories/