Android StatusBarUtil源碼閱讀

StatusBarUtil地址

setColor()設置狀態欄顏色

從設置狀態欄顏色方法開始看.

public class StatusBarUtil {
    /**
     * 設置狀態欄顏色
     *
     * @param activity 需要設置的 activity
     * @param color    狀態欄顏色值
     */
    public static void setColor(Activity activity, @ColorInt int color) {
        setColor(activity, color, DEFAULT_STATUS_BAR_ALPHA);
    }
    public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // 系統如果是5.0以上的走這裏
            // 繪製一個背景透明的狀態欄,然後用StatusBarColor中的顏色再去填充狀態欄.
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            // 清除FLAG_TRANSLUCENT_STATUS
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            // 這裏是設置狀態欄顏色
            activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 系統如果是4.4走這裏
            // FLAG_TRANSLUCENT_STATUS:設置狀態欄透明,並且爲全屏.
            // 在4.4的系統中,這樣設置以後DecorView整個佈局會向上移動後和狀態欄重合,
            // 所以下面會創建一個與狀態欄大小相同的佈局放入DecorView中,讓DecorView沒法向上移動與狀態欄重合.
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            // 找到當前Activity的DecorView
            ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
            // 獲取DecorView中自己創建的大小相同仿狀態欄View
            View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
            if (fakeStatusBarView != null) {
                // 如果仿狀態欄View在DecorView中找到了
                if (fakeStatusBarView.getVisibility() == View.GONE) {
                    fakeStatusBarView.setVisibility(View.VISIBLE);
                }
                // 設置這個仿狀態欄View背景色爲用戶希望的狀態欄顏色.
                // calculateStatusColor():該方法用來計算顏色的.
                fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
            } else {
                // 如果仿狀態欄View在DecorView中沒有找到,
                // 那麼就創建這個仿狀態欄View,然後將它添加到DecorView中第0位置.
                decorView.addView(createStatusBarView(activity, color, statusBarAlpha));
            }
            // 設置用戶佈局的paddingTop屬性以及繪製的區域.
            setRootView(activity);
        }
    }
    /**
     * 設置根佈局參數
     */
    private static void setRootView(Activity activity) {
        // 找到承載用戶佈局的父容器View.
        ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content);
        // 對該父容器中的子View遍歷
        for (int i = 0, count = parent.getChildCount(); i < count; i++) {
            View childView = parent.getChildAt(i);
            if (childView instanceof ViewGroup) {
                // 忽略用戶爲childView設置的padding屬性,將由系統爲該View設置paddingTop屬性,高度值爲狀態欄的高度.
                childView.setFitsSystemWindows(true);
                // 設置childView不在padding代表的區域中繪製.
                ((ViewGroup) childView).setClipToPadding(true);
            }
        }
    }

     /**
      * 生成一個和狀態欄大小相同的半透明矩形條
      *
      * @param activity 需要設置的activity
      * @param color    狀態欄顏色值
      * @param alpha    透明值
      * @return 狀態欄矩形條
      */
     private static View createStatusBarView(Activity activity, @ColorInt int color, int alpha) {
        // 繪製一個和狀態欄一樣高的矩形
        View statusBarView = new View(activity);
        // getStatusBarHeight() 獲取當前狀態欄的高度.
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
        statusBarView.setLayoutParams(params);
        // 設置仿狀態欄View的背景
        statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
        // 這一步是爲該View設置一個ID,方便到時候用這個ID找到該View.
        statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID);
        return statusBarView;
     }
}

至此,爲4.4版本和5.0以上版本的系統設置狀態欄的顏色就分析完成了,這裏做下總結:

  1. 4.4系統設置狀態欄顏色,首先設置狀態欄透明並且爲全屏,然後向DecorView中添加一個仿狀態欄的View,爲該View設置想要的顏色,然後爲用戶創建的佈局設置paddingTop屬性以及繪製的區域.
  2. 5.0以上系統設置狀態欄顏色相對簡單,調用一些API就能做到.
將佈局延申到狀態欄
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // 5.0以上系統做法
    // 繪製一個背景透明的狀態欄,然後用StatusBarColor中的顏色再去填充狀態欄.
    activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    // 爲狀態欄設置透明顏色
    activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
    // 透明導航欄
    activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    // 清除這個標記,4.4採用這個標記
    activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    // 視圖延伸至狀態欄區域,狀態欄上浮於視圖之上
	activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
} else {
    // 4.4系統做法
    // 設置狀態欄透明,並且爲全屏
    activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章