状态栏——字体颜色变黑

状态栏(一)
状态栏(三)

识别MIUI和FLyme系统

目前只看到了小米和魅族公开了各自的实现方法,支持底层Android4.4以上的版本。而Android官方在6.0版本才有了深色状态栏字体API。所以Android4.4以上系统版本可以修改状态栏颜色,但是只有小米的MIUI、魅族的Flyme和Android6.0以上系统可以把状态栏文字和图标换成深色。

我们首先要了解如何识别手机系统。
这篇文章告诉我们如何判断手机系统

整理出判断MIUI,FLyme系统的方法为

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
public class OSUtils {
public static final String ROM_MIUI = "MIUI";
public static final String ROM_FLYME = "FLYME";
private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name";

private static String sName;
private static String sVersion;

public static boolean isMiui() {
return check(ROM_MIUI);
}

public static boolean isFlyme() {
return check(ROM_FLYME);
}

public static boolean check(String rom) {
if (sName != null) {
return sName.equals(rom);
}
if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) {
sName = ROM_MIUI;
} else {
sVersion = Build.DISPLAY;
if (sVersion.toUpperCase().contains(ROM_FLYME)) {
sName = ROM_FLYME;
} else {
sVersion = Build.UNKNOWN;
sName = Build.MANUFACTURER.toUpperCase();
}
}
return sName.equals(rom);
}

public static String getProp(String name) {
String line = null;
BufferedReader input = null;
try {
Process p = Runtime.getRuntime().exec("getprop " + name);
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
line = input.readLine();
input.close();
} catch (IOException ex) {
Log.e(TAG, "Unable to read prop " + name, ex);
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return line;
}
}

设置状态栏透明

综合上一篇文章,我们知道Android4.4.+ ,API 19 以上可以设置状态栏透明,且 4.4 和 5.0 方式不同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 设置状态栏透明
*/
private void setTranslucentStatus() {

// 5.0以上系统状态栏透明
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = 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) { //19
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}

我们设置的主题为NoActionBar,除此之外没添加别的元素。
这里我给button添加了颜色,可以看到button顶到了状态栏。

添加状态栏高度

1
2
3
4
5
6
7
8
public int getStatusBarHeight() {
int statusBarHeight = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}

魅族字体设置方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void setFlymeUI(boolean dark) {
try {
Window window = getWindow();
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();
}
}

小米字体设置方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public void setMiuiUI(boolean dark) {
try {
Window window = getWindow();
Class clazz = getWindow().getClass();
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();
}
}

Android 6.0 以上设置方式

1
2
3
4
5
6
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

}

实现方式

这里介绍实现方式的一种,通过自定义基类的Activity,让所有要实现的Activity继承它。

我们的基类布局设置的方式为:状态栏+内容实现布局。
因此在实现过程中我们要将子类布局添加到我们的内容实现布局中,还要将状态栏设置为透明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<View
android:id="@+id/view_status_bar_place"
android:layout_width="match_parent"
android:layout_height="25dp"/>

<FrameLayout
android:id="@+id/frame_layout_content_place"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

总的实现方法为,下面是全部代码(要耐心看)

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
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;

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

/**
* Created by rhm on 2018/1/12.
*/

public class CompactActivity extends AppCompatActivity {
private FrameLayout mFrameLayoutContent;
private View mViewStatusBarPlace;
private final static int MIUI = 0;
private final static int FLYME = 1;
private final static int COMMON = 2;


@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_status_bar);
mViewStatusBarPlace = findViewById(R.id.view_status_bar_place);
mFrameLayoutContent = (FrameLayout) findViewById(R.id.frame_layout_content_place);

ViewGroup.LayoutParams params = mViewStatusBarPlace.getLayoutParams();
params.height = getStatusBarHeight();
mViewStatusBarPlace.setLayoutParams(params);
}

//将子类布局添加到FrameLayout中
@Override
public void setContentView(@LayoutRes int layoutResID) {
View contentView = LayoutInflater.from(this).inflate(layoutResID, null);
mFrameLayoutContent.addView(contentView);
}


/**
* 设置沉浸式状态栏
*
* @param fontIconDark 状态栏字体和图标颜色是否为深色
*/
protected void setImmersiveStatusBar(boolean fontIconDark) {
setTranslucentStatus();
if (fontIconDark) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setStatusBarFontIconDark(COMMON);
} else if (OSUtils.isMiui()) {
setStatusBarFontIconDark(MIUI);
} else if (OSUtils.isFlyme()) {
setStatusBarFontIconDark(FLYME);
} else {//其他情况下我们将状态栏设置为灰色,就不会看不见字体
setStatusBarPlaceColor(Color.LTGRAY);//灰色
}
}
}

/**
* 设置文字颜色
*/
public void setStatusBarFontIconDark(int type) {
switch (type) {
case MIUI:
setMiuiUI(true);
break;
case COMMON:
setCommonUI();
break;
case FLYME:
setFlymeUI(true);
break;
}
}

public void setCommonUI() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

}
}

public void setFlymeUI(boolean dark) {
try {
Window window = getWindow();
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();
}
}

public void setMiuiUI(boolean dark) {
try {
Window window = getWindow();
Class clazz = getWindow().getClass();
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();
}
}

public void setStatusBarPlaceColor(int statusColor) {
if (mViewStatusBarPlace != null) {
mViewStatusBarPlace.setBackgroundColor(statusColor);
}
}

/**
* 设置状态栏透明
*/
private void setTranslucentStatus() {

// 5.0以上系统状态栏透明
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = 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) { //19
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}

//设置状态栏高度
public int getStatusBarHeight() {
int statusBarHeight = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}
}

状态栏默认为主题颜色。可以根据需要设置状态栏的颜色,字体是否显示为黑色。
实现代码为:

1
2
3
4
5
6
7
8
9
public class MainActivity extends CompactActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setImmersiveStatusBar(true);
}
}

下一篇,我会介绍另一种实现方式。

参考文章
https://www.jianshu.com/p/a44c119d6ef7
http://yifeng.studio/2017/02/19/android-statusbar/

0%