零散知識點總結(3) Android 狀態欄知識點總結

1、概述

關於狀態欄的討論不少,咱們今天從需求的角度來看一下對於狀態欄的知識點:php

  • 不顯示狀態欄(4.4)
  • 經過Window
  • 經過DecorView
  • 顯示狀態欄
  • 靜態設置狀態欄透明(4.4)windowTranslucentStatus,須要解決重疊問題
    • 手動設置padding
    • fitsSystemWindows
  • 設置狀態欄顏色(5.0)
    • colorPrimaryDarkstyle中指定。
    • setStatusBarColor,動態設定。
  • 設置狀態欄和根佈局的層級關係(4.4)
    • SYSTEM_UI_FLAG_VISIBLE:狀態欄不覆蓋根佈局
    • SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN:狀態欄覆蓋根佈局
  • 動態設置狀態欄透明(5.0)
  • 改變狀態欄圖標顏色
  • 官方作法(6.0)
  • 魅族/小米作法

2、不顯示狀態欄

不顯示狀態欄通常用於屏幕可顯示區域較小的時候,而且要求可見面積較大的狀況,例如視頻、橫屏等,而不顯示狀態欄的方法有兩種,下面咱們分別介紹一下:html

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 小結 這兩種方法不能夠混合使用,也就是說,不能經過其中一種方法將狀態欄隱藏,又利用另外一種方法將它顯示出來。android

3、顯示狀態欄

在顯示狀態欄的狀況下,咱們將需求分爲如下三類:bash

3.1 設置狀態欄爲透明

要求安卓版本大於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

3.1.1 在佈局中加上和狀態欄高度相同的padding

這種方法有一點很差,就是咱們須要事先知道狀態欄的高度是多少,或者動態地獲取,並動態設置paddingcode

3.1.2 fitsSystemWindows

爲了解決上面的狀況,咱們能夠經過fitsSystemWindows屬性讓系統自動根據狀態欄的高度來給咱們的佈局留下足夠的空間。視頻

  • 在根佈局的xml中配置android:fitsSystemWindows屬性:
<LinearLayout android:fitsSystemWindows="true">
複製代碼

3.1.3 小結

須要注意,使用上面的方法來試狀態欄透明,須要在ActivityonCreate以前設置,若是在以後設置,那麼可能會出現意料以外的結果,若是想要在代碼當中設置狀態欄透明,那麼建議採用3.23.3的結合版本,也就是改變狀態欄顏色爲透明 + 改變佈局,咱們分析完下面的兩種以後,再看一下怎麼在代碼中設置。xml

3.2 改變狀態欄的顏色

在狀態欄不透明的狀況下,咱們能夠經過下面的方法來改變狀態欄的顏色,要求Android版本大於5.0

3.2.1 經過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,也不會使狀態欄和根佈局重疊。

3.2.2 經過代碼動態設置

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 小結

因爲上面討論的兩種方法都只能在5.0以上實現,所以若是咱們但願在5.0如下動態改變狀態欄的顏色,那麼就只能經過3.1中的方法,把狀態欄設置爲透明,而後在佈局中添加一個和狀態欄高度相同的背景,經過動態改變這個背景的顏色,來實現狀態欄顏色的改變。

3.3 改變狀態欄和根佈局的關係

其實在上面的兩種方法中,咱們也間接地改變了狀態欄和根佈局的關係,固然,咱們也能夠單純改變佈局關係,而不對狀態欄做出任何改變:

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 動態設置狀態欄透明

因爲這種方式結合了3.23.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);
            }
        }
    }
複製代碼

4、改變狀態欄圖標顏色

4.1 官方標準作法

這種方法要求AndroidAPI大於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 其它廠商作法

5、小結

5.1

總結下來,在顯示狀態欄的狀況下,適配範圍最廣的是下面這種方法:

  • 經過DecorView設置成透明而且重疊的模式(如3.4
  • 在根佈局中添加一個佈局,這個佈局的高度等於狀態欄的高度,這樣咱們就能夠經過控制它的高度和顏色來實現多種組合。
  • 若是想要改變圖標的顏色,就只能在6.0或者廠商的方法。

5.2

對於狀態欄的操做主要是兩種:一種是對DecorView操做,另外一種是對window操做,使用的時候對除了設置狀態欄顏色外的操做必定要保持統一,必定不要同時進行這兩種方法來進行相反的操做。舉個例子,若是採用了3.1中的對window進行操做使得狀態欄透明,並經過fitSystemWindows改變佈局,那麼就不要再採用3.3DecorView.setSystemUiVisibility()的方式來改變佈局的結構,最好是成對地出現,不然會使得佈局出現意料以外的狀況。

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 知識梳理系列:

相關文章
相關標籤/搜索