Fun Android status bar

Foreword

Some time ago, suddenly received a status bar color optimization task design, the original application overall black status bar amended as immersive design based on the title bar color display is as follows:


 
image

After analysis and stepped N cratered, finally completed the APP global changes. Some issues will now need to pay attention and to sort out stepped pit summary, the main differences are analyzed from the system version, ROM difference between major manufacturers and specific settings, also refer to during a lot of information, it will be accompanied by the corresponding link at the end of the text

Each version of the Android status bar difference

First, we need to pay attention, Android versions are not supported color settings of the status bar, only supported more than 5.0. In addition more than 6.0 only supports setting black status bar icon (avoid white and white icon in the status bar result in power not see the time and other issues)

 
image
system version Whether to support the setting status bar color Allow to set status bar black icon
4.4 no no
5.0 Yes no
6.0+ Yes Yes

Each ROM Status Bar difference

The status bar is not set up to really transparent transparent up?

This problem also plagued me a start, back analysis, the native system, while setting up a transparent status bar, status bar area but there will be a layer of translucent mask (it is estimated that taking into account the problems caused by the white status bar), but testing found that some domestic ROM set will be completely transparent to penetrate the transparent column (such as MIUI)

Native system effects are as follows:


 
image

MIUI system effects are as follows:


 
image

6.0 is not supported by the system status bar black bar icon?

There are more than 6.0 Native API support, but China-made ROM customized, and some require specific settings can be achieved

Native system settings:

  public void setLightStatusBar(Window window, boolean lightStatusBar) {
            // 设置浅色状态栏时的界面显示
            View decor = window.getDecorView();
            int ui = decor.getSystemUiVisibility();
            if (lightStatusBar) {
                ui |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            } else {
                ui &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            }
            decor.setSystemUiVisibility(ui);

        }
小米:

public static boolean MIUISetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            Class clazz = window.getClass();
            try {
                int darkModeFlag = 0;
                Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                if (dark) {
                    extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
                } else {
                    extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
                }
                result = true;
            } catch (Exception e) {

            }
        }
        return result;
    }

 

魅族:

public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            try {
                WindowManager.LayoutParams lp = window.getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class
                        .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class
                        .getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                result = true;
            } catch (Exception e) {

            }
        }
        return result;
    }

 

华为手机:
部分测试发现华为的EMUI手机状态栏会跟系统桌面的状态栏一样,设置了没用,这里如果要特殊设置状态栏颜色,只能参考4.4的处理方式(后续介绍)

 
image

如何进行定制状态栏

原理分析

  • 4.4

通过上述的版本及分析,可见完善的的状态栏兼容是一个大工程,需要综合考虑系统版本及各个厂商ROM等因素。5.0以上有系统API进行支持,这里我们主要来分析一些4.4的实现原理。
简单来说,4.4的实现方式就是使用透明的状态栏,然后做一个和状态栏一样高度的View,加入到Windows的DecorView,然后给这个View设置背景色,达到实现状态栏颜色。

 window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup decorViewGroup = (ViewGroup) window.getDecorView();
        View statusBarView = decorViewGroup.findViewWithTag(STATUS_BAR_VIEW_TAG);
        if (statusBarView == null) {
            statusBarView = new StatusBarView(window.getContext());
            statusBarView.setTag(STATUS_BAR_VIEW_TAG);
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
                    FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
            params.gravity = Gravity.TOP;
            statusBarView.setLayoutParams(params);
            decorViewGroup.addView(statusBarView);
        }
        statusBarView.setBackgroundColor(color);
        StatusBarCompat.internalSetFitsSystemWindows(window, true);

 

 
image
  • 5.0

注意5.0一般不用使用白色的状态栏(因为不能设置状态栏灰色图标),可在资源文件定义一个rgb,区分版本,5.0使用白灰色

 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public void setStatusBarColor(Window window, int color) {
        //取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        //需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        //设置状态栏颜色
        window.setStatusBarColor(color);
    }

 

 
image
  • 6.0
 @TargetApi(Build.VERSION_CODES.M)
    @Override
    public void setStatusBarColor(Window window, int color) {
        //取消设置透明状态栏,使 ContentView 内容不再覆盖状态栏
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        //需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        //设置状态栏颜色
        window.setStatusBarColor(color);

        // 去掉系统状态栏下的windowContentOverlay
        View v = window.findViewById(android.R.id.content);
        if (v != null) {
            v.setForeground(null);
        }
    }

 

 
image

实现方案

这里不重复造轮子,先提供一下github上比较完善的处理方案

status-bar-compat

StatusBarCompat是一个用于设置系统状态栏颜色的兼容库,兼容Android 4.4.2(API 19)以上,使用简单,仅需要一行代码的调用。

SystemBarTint

支持4.4以上的,主要使用透明状态栏的方式实现

推荐使用status-bar-compat,已考虑到整体的版本兼容机及各厂ROM,调用简单。

在Activity的setContentView()方法调用之后,调用以下方法即可。
 StatusBarCompat.setStatusBarColor(this, color, lightStatusBar);
或者是

    StatusBarCompat.setStatusBarColor(this, color);

 

本文主要源码使用status-bar-compat中的代码进行说明

关于全屏及非全屏界面切换导致页面移动问题

例如在应用中有全屏的看图页面,点击返回为非全屏(带状态栏)页面,非全屏页面由于现实状态,会出现页面抖动。目前暂无完善的处理方案,项目中暂时使用的方式是延迟全屏页面的finish,先显示状态栏后再关闭

复写onBackPressed
getActivity().getWindow().clearFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        if(getView()!=null){
            getView().postDelayed(new Runnable() {
                @Override
                public void run() {
                    getActivity().finish();
                }
            },10);
        }

 

状态栏一片白色

上面已有分析,要注意如果状态栏为白色,需要设置状态栏的图标颜色。status-bar-compat中会把颜色转换成灰度值,然后自己控制状态栏图标颜色

 public static void setStatusBarColor(Activity activity, @ColorInt int color) {
        boolean isLightColor = toGrey(color) > 225;
        setStatusBarColor(activity, color, isLightColor);
    }

    /**
     * 把颜色转换成灰度值。
     * 代码来自 Flyme 示例代码
     */
    public static int toGrey(@ColorInt int color) {
        int blue = Color.blue(color);
        int green = Color.green(color);
        int red = Color.red(color);
        return (red * 38 + green * 75 + blue * 15) >> 7;
    }

 

Part elastic layer of third-party components and white status bar seemed more abrupt

 
image

This is also no way be considered when the bomb layer occurs, the color of dynamic modification of the state, but the workload is relatively large, can be adjusted rgb first bomb layer, reduce transparency

Reference material

Android 6.0 or higher to achieve the status bar black and white

status-bar-compat



Author: Huangjun Bin
link: https: //www.jianshu.com/p/ace8f7921cde
Source: Jane book
Jane book copyright reserved by the authors, are reproduced in any form, please contact the author to obtain authorization and indicate the source.

Guess you like

Origin www.cnblogs.com/Im-Victor/p/11362082.html