当前位置: 首页 > 工具软件 > StatusBarUtil > 使用案例 >

Android StatusBarUtil源码阅读

吕志诚
2023-12-01

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);
}
 类似资料: