功能需求
设计说,手机的状态栏应该适配app颜色;该app的颜色主要是白色——但是状态栏是手机默认的蓝色。
解决
参考资料
代码
package im.zego.goclass.tool;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import androidx.annotation.ColorInt;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class StatusBarUtils {
//https://www.jianshu.com/p/932568ed31af
public static void immersiveNotificationBar(Activity activity) {
immersiveNotificationBar(activity, Color.WHITE);
}
/**
* 设置沉浸式状态栏
*/
public static void immersiveNotificationBar(Activity activity, int color) {
String brand = Build.BRAND;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//字体颜色改为黑色,非白色沉浸式状态栏不需要设置
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
activity.getWindow().setStatusBarColor(Color.WHITE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//解决华为手机等状态栏上面有一个蒙层问题
try {
Class decorViewClazz = Class.forName("com.android.internal.policy.DecorView");
Field field = decorViewClazz.getDeclaredField("mSemiTransparentStatusBarColor");
field.setAccessible(true);
field.setInt(activity.getWindow().getDecorView(), Color.TRANSPARENT); //改为透明
} catch (Exception e) {
Log.w(TAG,"No field mSemiTransparentStatusBarColor in class");
}
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
if (color == Color.WHITE) {
//Meizu,Xiaomi,Letv
if ("Xiaomi".equalsIgnoreCase(brand)) {
activity.getWindow().setStatusBarColor(Color.WHITE);
setMiuiStatusBarDarkMode(activity, true);
} else if ("Meizu".equalsIgnoreCase(brand)) { //魅族好像不需要设置,自动变黑字
activity.getWindow().setStatusBarColor(Color.WHITE);
setMeizuStatusBarDarkIcon(activity, true);
} else {
activity.getWindow().setStatusBarColor(0xFFDDDDDD);
}
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if ("vivo".equals(brand)) {
// http://bbs.vivo.com.cn/forum.php?mobile=1&mod=viewthread&tid=2070149 ::
// vivo手机只有Android5.0及以上的机型才支持沉浸式状态栏
// 设置透明不生效,而且还会导致页面偏移到状态栏下面,放弃处理
} else {
ViewGroup contentParent = activity.getWindow().findViewById(android.R.id.content);
if (contentParent == null) {
// 部分机型和系统上,甚至改了这个id,导致找不到,放弃处理
} else {
//设置透明,再蒙上一层我们设置的颜色的背景,这样状态栏就像是设置了背景色一样
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
int count = decorView.getChildCount();
if (count > 0 && null != decorView.getChildAt(count - 1)) {
decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, 30));
} else {
View statusView = createStatusBarView(activity, color, 30);
decorView.addView(statusView);
}
//但是设置透明以后,状态栏会叠加到contentview上面去,所以需要setFitsSystemWindows来让它为状态栏让出一定的距离
ViewGroup rootView = (ViewGroup) contentParent.getChildAt(0);
rootView.setFitsSystemWindows(true);
rootView.setClipToPadding(true);
}
}
}
}
private static View createStatusBarView(Activity activity, @ColorInt int color, int alpha) {
View statusBarView = new View(activity);
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
statusBarView.setLayoutParams(params);
statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
return statusBarView;
}
/**
* 小米的官方解决方案
*
* @param activity
* @param darkmode
* @return
*/
private static boolean setMiuiStatusBarDarkMode(Activity activity, boolean darkmode) {
Class<? extends Window> clazz = activity.getWindow().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);
extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static boolean setMeizuStatusBarDarkIcon(Activity activity, boolean dark) {
boolean result = false;
if (activity != null) {
try {
WindowManager.LayoutParams lp = activity.getWindow().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);
activity.getWindow().setAttributes(lp);
result = true;
} catch (Exception e) {
}
}
return result;
}
private static final String TAG = "StatusBarUtils";
private static int calculateStatusColor(@ColorInt int color, int alpha) {
float a = 1 - alpha / 255f;
int red = color >> 16 & 0xff;
int green = color >> 8 & 0xff;
int blue = color & 0xff;
red = (int) (red * a + 0.5);
green = (int) (green * a + 0.5);
blue = (int) (blue * a + 0.5);
return 0xff << 24 | red << 16 | green << 8 | blue;
}
public static int getStatusBarHeight(Context context) {
int statusBarHeight1 = -1;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight1 = context.getResources().getDimensionPixelSize(resourceId);
}
return statusBarHeight1;
}
public static void fullScreenWithTransparentStatusBar(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色
Window window = activity.getWindow();
View decorView = window.getDecorView();
//两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
decorView.setSystemUiVisibility(option);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
//导航栏颜色也可以正常设置
// window.setNavigationBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window window = activity.getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
attributes.flags |= flagTranslucentStatus;
// attributes.flags |= flagTranslucentNavigation;
window.setAttributes(attributes);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//解决华为手机等状态栏上面有一个蒙层问题
try {
Class decorViewClazz = Class.forName("com.android.internal.policy.DecorView");
Field field = decorViewClazz.getDeclaredField("mSemiTransparentStatusBarColor");
field.setAccessible(true);
field.setInt(activity.getWindow().getDecorView(), Color.TRANSPARENT); //改为透明
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
}