StatusBar常用方法使用总结

本文主要总结状态栏沉浸式的常用方法。

  • 改变状态栏颜色
  • 设置透明状态栏
  • 改变状态栏字体颜色及国产机适配
  • 其他相关方法
  • 使用示例

由于最近比较忙,所以这里写得比较简洁。
我不赞成使用第三方库,因为一般来说下面的方法使用就足够了。
推荐只用设置沉浸式状态栏方法,然后,自己给状态栏模块着色。这样图片或者单色都可以自己控制显示


改变状态栏颜色

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 设置状态栏颜色
* @param activity 需要设置的activity
* @param color 状态栏颜色值
*/
public static void setColor(Activity activity, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().setStatusBarColor(color);
}
}

设置透明状态栏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 设置状态栏透明
* @param activity 需要设置的activity
*/
private static void setTranslucentStatus(Activity activity) {
if (activity == null) {
return;
}
Window window = activity.getWindow();
// 5.0以上系统状态栏透明
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}

改变状态栏字体颜色及国产机适配

  • OsUtils.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    public static boolean isMIUI() {
    return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.name"));
    }

    public static boolean isFlyme() {
    try {
    final Method method = Build.class.getMethod("hasSmartBar");
    return method != null;
    } catch (final Exception e) {
    return false;
    }
    }

    private static String getSystemProperty(String propName) {
    String line;
    BufferedReader input = null;
    try {
    java.lang.Process p = Runtime.getRuntime().exec("getprop " + propName);
    input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
    line = input.readLine();
    input.close();
    } catch (IOException ex) {
    return null;
    } finally {
    if (input != null) {
    try {
    input.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    return line;
    }
  • 设置沉浸式状态栏

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    /**
    * 设置沉浸式状态栏
    * @param activity
    * @param fontIconDark 状态栏字体和图标颜色是否为深色
    * @param fontIconDark 状态栏字体是否为深色
    * @param statusBarPlaceColor 状态栏需要设置的颜色
    * @return 这里返回的颜色用于设置给状态栏那块的颜色,避免出现 背景为Color.WHITE的深色字体看不清的情况
    */
    public static int setImmersiveStatusBar(Activity activity,boolean fontIconDark, int statusBarPlaceColor) {
    if (activity == null) {
    return statusBarPlaceColor;
    }
    setTranslucentStatus(activity);
    if (fontIconDark) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
    || OsUtils.isMIUI()
    || OsUtils.isFlyme()) {
    setStatusBarFontIconDark(activity,true);
    } else {
    if (statusBarPlaceColor == Color.WHITE) {//这里主要是为了避免白底白子看不清楚
    statusBarPlaceColor = 0xffcccccc;
    }
    }
    }else{
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
    || OsUtils.isMIUI()
    || OsUtils.isFlyme()) {
    setStatusBarFontIconDark(activity,false);
    }
    }
    return statusBarPlaceColor;
    }

    /**
    * 设置Android状态栏的字体颜色,状态栏为亮色的时候字体和图标是黑色,状态栏为暗色的时候字体和图标为白色
    * @param dark 状态栏字体是否为深色
    */
    private static void setStatusBarFontIconDark(Activity activity, boolean dark) {
    if (activity == null) {
    return;
    }
    Window window = activity.getWindow();
    if (window != null) {
    Class clazz = window.getClass();
    // 小米MIUI
    try {
    Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
    Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
    int 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);
    }
    } catch (Exception e) {
    e.printStackTrace();
    }

    // 魅族FlymeUI
    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);
    } catch (Exception e) {
    e.printStackTrace();
    }
    // android6.0+系统
    // 这个设置和在xml的style文件中用这个<item name="android:windowLightStatusBar">true</item>属性是一样的
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    if (dark) {
    window.getDecorView().setSystemUiVisibility(
    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    }
    }
    }
    }

    /**
    * 需要MIUIV6以上
    *
    * @param activity
    * @param dark 是否把状态栏文字及图标颜色设置为深色
    * @return boolean 成功执行返回true
    */
    public static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
    boolean result = false;
    Window window = activity.getWindow();
    if (window != null) {
    Class clazz = window.getClass();
    try {
    Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
    Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
    int 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;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    //开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
    if (dark) {
    activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);//View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|
    } else {
    activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
    }
    }
    } catch (Exception e) {

    }
    }
    return result;
    }

    /**
    * 设置状态栏图标为深色和魅族特定的文字风格
    * 可以用来判断是否为Flyme用户
    *
    * @param window 需要设置的窗口
    * @param dark 是否把状态栏文字及图标颜色设置为深色
    * @return boolean 成功执行返回true
    */
    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;
    }

其他相关方法

  • 获取状态栏高度
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public static int getStatusBarHeight(Activity activity) {
    if (activity == null) {
    return -1;
    }
    int statusBarHeight = 0;
    int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
    statusBarHeight = activity.getResources().getDimensionPixelSize(resourceId);
    }
    return statusBarHeight;
    }

使用示例

这里为了赶时间,简洁说明。

  • 只是单色可以选择第一种方法
  • 也可以用下面这种,自己添加和状态栏一样高的view(该view可以封装在activity或fragment的base中,前提是内容能在顶部显示的情况下,同时需要满足Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)才有这个view),设置颜色。
    1
    2
    3
    4
    5
    //该代码在需要的activity里面调用
    //可支持在FragmentTabHost实现的界面,多次调用,实现不同的状态栏
    int statusbarcolor = StatusBarUtil.setImmersiveStatusBar(activity, false, getResources().getColor(R.color.red);
    //1.如果只是单色,可将自己添加的状态栏高度那块view设置背景色为statusbarcolor即可。
    //2.如果是图片等,什么都不用,直接支持。你的内容将会在透明状态下直接显示。
    注意:需要给activity指定主题,不需要activitBar
    1
    2
    3
    4
    5
    6
    <style name="AppStandardTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="windowNoTitle">true</item>
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorDefault</item>
    </style>