Android状态栏颜色修改

前言

Android 4.4(API 19)之后,就提供了修改状态栏颜色的方法,但是在 Android 6.0(API 23)之后,才支持修改状态栏上面的文字和图标颜色,默认是白色的。所以会导致一个问题,在 4.4 到 6.0 之间的系统,状态栏设置为浅色的话,状态栏上面白色的文字和图标会看不清

有一些第三方的系统提供了设置状态栏和状态栏文字、图标颜色的方法,比如小米的MIUI和魅族的Flyme,所以考虑了下比较好的实现方式是:

  • Android 4.4 以上使用 SystemBarTint 修改状态栏颜色;
  • Android 6.0 以上使用系统方法修改状态栏字体、图标颜色;
  • Android 4.4 到 6.0 之间使用第三方系统提供的方法修改状态栏字体、图标颜色(目前只有 MIUI 和 Flyme)。

当然,这里面也会有坑,比如 MIUI 提供的修改状态栏字体颜色方法会跟 Android 系统自带的方法冲突,官方说明如下: 关于MIUI状态栏字符颜色逻辑调整说明
经过网上的资料和自己的尝试,MIUI 系统还是同时使用 MIUI 提供的方法和 Android 系统自带的方法来修改状态栏字体颜色比较保险。

基于上面的思考,封装了设置 Android 4.4 以上系统状态栏颜色和状态栏字体、图标颜色的方法:

首先,需要引入 SystemBarTint 库:

1
2
3
dependencies {
implementation 'com.readystatesoftware.systembartint:systembartint:1.0.3'
}

隐藏标题栏

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<!--标题栏的颜色-->
<item name="colorPrimary">@color/colorPrimary</item>
<!--状态栏的颜色-->
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<!--默认的光标、选中的RadioButton颜色-->
<item name="colorAccent">@color/colorAccent</item>
<!-- 避免控件会顶到状态栏上 -->
<item name="android:fitsSystemWindows">true</item>
</style>

要在 Application Theme 加上

1
<item name="android:fitsSystemWindows">true</item>

不然页面会顶到状态栏上面,

或者

在 Activity 的布局里面加上

1
2
android:fitsSystemWindows="true"
android:clipToPadding="false"

也可以。

工具类

状态栏工具类 StatusBarUtil.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
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
164
165
166
167
168
169
170
171
172
173
174
import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Color;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import com.readystatesoftware.systembartint.SystemBarTintManager;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
* 状态栏工具类
*/
public class StatusBarUtil {

/**
* 设置状态栏为透明
* @param activity
*/
@TargetApi(19)
public static void setTranslucentStatus(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
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 window = activity.getWindow();
window.setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
);
}
}

/**
* 修改状态栏颜色,支持4.4以上版本
* @param activity
* @param colorId
*/
public static void setStatusBarColor(Activity activity, int colorId) {
//Android6.0(API 23)以上,系统方法
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = activity.getWindow();
window.setStatusBarColor(activity.getResources().getColor(colorId));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//使用SystemBarTint库使4.4版本状态栏变色,需要先将状态栏设置为透明
setTranslucentStatus(activity);
//设置状态栏颜色
SystemBarTintManager tintManager = new SystemBarTintManager(activity);
tintManager.setStatusBarTintEnabled(true);
tintManager.setStatusBarTintResource(colorId);
}
}

/**
* 设置状态栏模式
* @param activity
* @param isTextDark 文字、图标是否为黑色 (false为默认的白色)
* @param colorId 状态栏颜色
* @return
*/
public static void setStatusBarMode(Activity activity, boolean isTextDark, int colorId) {

if(!isTextDark) {
//文字、图标颜色不变,只修改状态栏颜色
setStatusBarColor(activity, colorId);
} else {
//修改状态栏颜色和文字图标颜色
setStatusBarColor(activity, colorId);
//4.4以上才可以改文字图标颜色
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if(OSUtil.isMIUI()) {
//小米MIUI系统
setMIUIStatusBarTextMode(activity, isTextDark);
} else if(OSUtil.isFlyme()) {
//魅族flyme系统
setFlymeStatusBarTextMode(activity, isTextDark);
} else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//6.0以上,调用系统方法
Window window = activity.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
//4.4以上6.0以下的其他系统,暂时没有修改状态栏的文字图标颜色的方法,有可以加上
}
}
}
}

/**
* 设置Flyme系统状态栏的文字图标颜色
* @param activity
* @param isDark 状态栏文字及图标是否为深色
* @return
*/
public static boolean setFlymeStatusBarTextMode(Activity activity, boolean isDark) {
Window window = activity.getWindow();
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 (isDark) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
window.setAttributes(lp);
result = true;
} catch (Exception e) {

}
}
return result;
}

/**
* 设置MIUI系统状态栏的文字图标颜色(MIUIV6以上)
* @param activity
* @param isDark 状态栏文字及图标是否为深色
* @return
*/
public static boolean setMIUIStatusBarTextMode(Activity activity, boolean isDark) {
boolean result = false;
Window window = activity.getWindow();
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 (isDark) {
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 (isDark) {
activity.getWindow().getDecorView().setSystemUiVisibility(View
.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View
.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
activity.getWindow().getDecorView().setSystemUiVisibility(View
.SYSTEM_UI_FLAG_VISIBLE);
}
}
} catch (Exception e) {

}
}
return result;
}
}

设备系统工具类 OSUtil.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
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
import android.os.Environment;
import android.text.TextUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
* 设备系统工具类
*/

public class OSUtil {
//MIUI标识
private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
private static final String KEY_MIUI_INTERNAL_STORAGE = "ro.miui.internal.storage";

//EMUI标识
private static final String KEY_EMUI_VERSION_CODE = "ro.build.version.emui";
private static final String KEY_EMUI_API_LEVEL = "ro.build.hw_emui_api_level";
private static final String KEY_EMUI_CONFIG_HW_SYS_VERSION = "ro.confg.hw_systemversion";

//Flyme标识
private static final String KEY_FLYME_ID_FALG_KEY = "ro.build.display.id";
private static final String KEY_FLYME_ID_FALG_VALUE_KEYWORD = "Flyme";
private static final String KEY_FLYME_ICON_FALG = "persist.sys.use.flyme.icon";
private static final String KEY_FLYME_SETUP_FALG = "ro.meizu.setupwizard.flyme";
private static final String KEY_FLYME_PUBLISH_FALG = "ro.flyme.published";

/**
* 是否是Flyme系统
* @return
*/
public static boolean isFlyme() {
if(isPropertiesExist(KEY_FLYME_ICON_FALG, KEY_FLYME_SETUP_FALG, KEY_FLYME_PUBLISH_FALG)) {
return true;
}
try {
BuildProperties buildProperties = BuildProperties.newInstance();
if(buildProperties.containsKey(KEY_FLYME_ID_FALG_KEY)) {
String romName = buildProperties.getProperty(KEY_FLYME_ID_FALG_KEY);
if (!TextUtils.isEmpty(romName) && romName.contains(KEY_FLYME_ID_FALG_VALUE_KEYWORD)) {
return true;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}

/**
* 是否是EMUI系统
* @return
*/
public static boolean isEMUI() {
return isPropertiesExist(KEY_EMUI_VERSION_CODE, KEY_EMUI_API_LEVEL,
KEY_EMUI_CONFIG_HW_SYS_VERSION);
}

/**
* 是否是MIUI系统
* @return
*/
public static boolean isMIUI() {
return isPropertiesExist(KEY_MIUI_VERSION_CODE, KEY_MIUI_VERSION_NAME,
KEY_MIUI_INTERNAL_STORAGE);
}

private static boolean isPropertiesExist(String... keys) {
if (keys == null || keys.length == 0) {
return false;
}
try {
BuildProperties properties = BuildProperties.newInstance();
for (String key : keys) {
String value = properties.getProperty(key);
if (value != null)
return true;
}
return false;
} catch (IOException e) {
return false;
}
}

private static final class BuildProperties {

private final Properties properties;

private BuildProperties() throws IOException {
properties = new Properties();
//读取系统配置信息build.prop类
properties.load(
new FileInputStream(
new File(Environment.getRootDirectory(), "build.prop")
)
);
}

public boolean containsKey(final Object key) {
return properties.containsKey(key);
}

public boolean containsValue(final Object value) {
return properties.containsValue(value);
}

public Set<Map.Entry<Object, Object>> entrySet() {
return properties.entrySet();
}

public String getProperty(final String name) {
return properties.getProperty(name);
}

public String getProperty(final String name, final String defaultValue) {
return properties.getProperty(name, defaultValue);
}

public boolean isEmpty() {
return properties.isEmpty();
}

public Enumeration<Object> keys() {
return properties.keys();
}

public Set<Object> keySet() {
return properties.keySet();
}

public int size() {
return properties.size();
}

public Collection<Object> values() {
return properties.values();
}

public static BuildProperties newInstance() throws IOException {
return new BuildProperties();
}
}
}

在 Activity 里面调用:

1
2
//根据状态栏颜色来决定状态栏文字用黑色还是白色
StatusBarUtil.setStatusBarMode(this, true, R.color.color_f3);

最终实现的效果如下:

img

转载自:https://www.jianshu.com/p/3042bf7d72e3