關於狀態欄的討論不少,咱們今天從需求的角度來看一下對於狀態欄的知識點:php
(4.4)
Window
DecorView
(4.4)
:windowTranslucentStatus
,須要解決重疊問題
padding
fitsSystemWindows
(5.0)
:
colorPrimaryDark
,style
中指定。setStatusBarColor
,動態設定。(4.4)
:
SYSTEM_UI_FLAG_VISIBLE
:狀態欄不覆蓋根佈局SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
:狀態欄覆蓋根佈局(5.0)
(6.0)
不顯示狀態欄通常用於屏幕可顯示區域較小的時候,而且要求可見面積較大的狀況,例如視頻、橫屏等,而不顯示狀態欄的方法有兩種,下面咱們分別介紹一下:html
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);
}
}
複製代碼
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 小結 這兩種方法不能夠混合使用,也就是說,不能經過其中一種方法將狀態欄隱藏,又利用另外一種方法將它顯示出來。android
在顯示狀態欄的狀況下,咱們將需求分爲如下三類:bash
要求安卓版本大於4.4。 咱們能夠在style
中指定,而後設置給Activity
或者Application
:佈局
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowTranslucentStatus">true</item>
</style>
複製代碼
固然,也能夠經過代碼來指定:ui
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);
}
}
複製代碼
解決狀態欄透明時和根佈局重疊的問題 這兩種方法是等效的,可是它們都存在一個問題,根佈局會和狀態欄重疊,這時候就有兩種解決辦法:spa
padding
這種方法有一點很差,就是咱們須要事先知道狀態欄的高度是多少,或者動態地獲取,並動態設置padding
。code
fitsSystemWindows
爲了解決上面的狀況,咱們能夠經過fitsSystemWindows
屬性讓系統自動根據狀態欄的高度來給咱們的佈局留下足夠的空間。視頻
xml
中配置android:fitsSystemWindows
屬性:<LinearLayout android:fitsSystemWindows="true">
複製代碼
須要注意,使用上面的方法來試狀態欄透明,須要在Activity
的onCreate
以前設置,若是在以後設置,那麼可能會出現意料以外的結果,若是想要在代碼當中設置狀態欄透明,那麼建議採用3.2
和3.3
的結合版本,也就是改變狀態欄顏色爲透明 + 改變佈局,咱們分析完下面的兩種以後,再看一下怎麼在代碼中設置。xml
在狀態欄不透明的狀況下,咱們能夠經過下面的方法來改變狀態欄的顏色,要求Android
版本大於5.0
:
style
設置其中colorPrimaryDark
就是指定的狀態欄顏色
<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
,也不會使狀態欄和根佈局重疊。
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));
}
}
}
複製代碼
因爲上面討論的兩種方法都只能在5.0
以上實現,所以若是咱們但願在5.0
如下動態改變狀態欄的顏色,那麼就只能經過3.1
中的方法,把狀態欄設置爲透明,而後在佈局中添加一個和狀態欄高度相同的背景,經過動態改變這個背景的顏色,來實現狀態欄顏色的改變。
其實在上面的兩種方法中,咱們也間接地改變了狀態欄和根佈局的關係,固然,咱們也能夠單純改變佈局關係,而不對狀態欄做出任何改變:
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.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);
}
}
}
複製代碼
這種方法要求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);
}
}
}
複製代碼
總結下來,在顯示狀態欄的狀況下,適配範圍最廣的是下面這種方法:
DecorView
設置成透明而且重疊的模式(如3.4
)6.0
或者廠商的方法。對於狀態欄的操做主要是兩種:一種是對DecorView
操做,另外一種是對window
操做,使用的時候對除了設置狀態欄顏色外的操做必定要保持統一,必定不要同時進行這兩種方法來進行相反的操做。舉個例子,若是採用了3.1
中的對window
進行操做使得狀態欄透明,並經過fitSystemWindows
改變佈局,那麼就不要再採用3.3
中DecorView.setSystemUiVisibility()
的方式來改變佈局的結構,最好是成對地出現,不然會使得佈局出現意料以外的狀況。
最後附上代碼:
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);
}
}
}
}
複製代碼