之前找的别人的,当时没保存地址,所以没办法贴上原作者的引用。但是直到今天,发现他的这个在全面屏手机上会有点点问题。
一般我们开发的时候,会遇到首页的Activity放置四五个Fragment,然后第一个Fragment沉浸式,后面的不沉浸式,最后找到一个很好的解决办法是:
让第一个Fragment让状态栏透明:
/**
* 状态栏透明
* @param activity
*/
@TargetApi(19)
public static void transparencyBar(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);
window.setNavigationBarColor(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);
}
}
剩余的Fragment,在最上边添加一个View
然后在后面所有不需要沉浸式的Fragment里面获取状态栏的高度并设置给这个View,并设置好颜色
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_shopcart, container, false);
View mStateBarFixer = view.findViewById(R.id.status_bar_custom);
mStateBarFixer.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(getActivity())));
mStateBarFixer.setBackgroundColor(getResources().getColor(R.color.black));
....
return view;
}
/**
* 获取状态栏高度
*
* @param context context
* @return 状态栏高度
*/
public static int getStatusBarHeight(Context context) {
int result = 0;
// 获得状态栏高度
int resourceId = context.getResources().getIdentifier("status_bar_height",
"dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
但是这样弄好之后,字体颜色又需要改变,我这边的方法是在需要重新设置字体颜色的Fragment里,重写当前这个Fragment里面的onHiddenChanged方法即可,如果只是第一个Fragment里面沉浸,后面都不沉浸,可以在第一个Fragment里面重写就行。我代码里还在onCreateView里面设置了下。
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
// false为白色字体,true为黑色字体
if(hidden){
UtilsStyle.setLightStatusBar(getActivity(),false);
} else {
refresh();
UtilsStyle.setLightStatusBar(getActivity(),true);
}
}
下面是这个工具类:
/**
* Created by Leon on 2019/1/12 Copyright © Leon. All rights reserved.
* Functions: 设置状态栏透明并改变状态栏颜色为深色工具类
*/
public class UtilsStyle {
class AvailableRomType {
public static final int MIUI = 1;
public static final int FLYME = 2;
public static final int ANDROID_NATIVE = 3;
public static final int NA = 4;
}
private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code";
/**
* 修改状态栏文字颜色,这里小米,魅族区别对待。
*/
public static void setLightStatusBar(final Activity activity, final boolean dark) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
switch (getLightStatusBarAvailableRomType()) {
case AvailableRomType.MIUI:
MIUISetStatusBarLightMode(activity, dark);
break;
case AvailableRomType.FLYME:
FLYMESetStatusBarLightMode(activity, dark);
break;
case AvailableRomType.ANDROID_NATIVE:
setAndroidNativeLightStatusBar(activity, dark);
break;
}
}
}
public static int getLightStatusBarAvailableRomType() {
//开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错
if (isMiUIV7OrAbove()) {
return AvailableRomType.ANDROID_NATIVE;
}
if (isMiUIV6OrAbove()) {
return AvailableRomType.MIUI;
}
if (isFlymeV4OrAbove()) {
return AvailableRomType.FLYME;
}
if (isAndroidMOrAbove()) {
return AvailableRomType.ANDROID_NATIVE;
}
return AvailableRomType.NA;
}
/**
* 需要MIUIV6以上
*
* @param dark 是否把状态栏文字及图标颜色设置为深色
* @return boolean 成功执行返回true
*/
private static boolean MIUISetStatusBarLightMode(Activity activity, boolean dark) {
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 (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_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |View.SYSTEM_UI_FLAG_VISIBLE);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
/**
* 设置状态栏图标为深色和魅族特定的文字风格
* 可以用来判断是否为Flyme用户
*
* @param activity 需要设置的窗口
* @param dark 是否把状态栏文字及图标颜色设置为深色
* @return boolean 成功执行返回true
*/
private static boolean FLYMESetStatusBarLightMode(Activity activity, boolean dark) {
boolean result = false;
Window window = activity.getWindow();
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;
}
public static boolean isMiUIV6OrAbove() {
String miuiVersionCodeStr = getSystemProperty("ro.miui.ui.version.code");
if (!TextUtils.isEmpty(miuiVersionCodeStr)) {
try {
int miuiVersionCode = Integer.parseInt(miuiVersionCodeStr);
if (miuiVersionCode >= 4) {
return true;
}
} catch (Exception e) {
}
}
return false;
}
static boolean isMiUIV7OrAbove() {
try {
final Properties properties = new Properties();
properties.load(new FileInputStream(new File(Environment.getRootDirectory(), "build.prop")));
String uiCode = properties.getProperty(KEY_MIUI_VERSION_CODE, null);
if (uiCode != null) {
int code = Integer.parseInt(uiCode);
return code >= 5;
} else {
return false;
}
} catch (final Exception e) {
return false;
}
}
//Flyme V4的displayId格式为 [Flyme OS 4.x.x.xA]
//Flyme V5的displayId格式为 [Flyme 5.x.x.x beta]
private static boolean isFlymeV4OrAbove() {
String displayId = Build.DISPLAY;
if (!TextUtils.isEmpty(displayId) && displayId.contains("Flyme")) {
String[] displayIdArray = displayId.split(" ");
for (String temp : displayIdArray) {
//版本号4以上,形如4.x.
if (temp.matches("^[4-9]\\.(\\d+\\.)+\\S*")) {
return true;
}
}
}
return false;
}
//Android Api 23以上
private static boolean isAndroidMOrAbove() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
public static void setAndroidNativeLightStatusBar(Activity activity, boolean dark) {
View decor = activity.getWindow().getDecorView();
if (dark) {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
}
private static String getSystemProperty(String propName) {
String line;
BufferedReader input = null;
try {
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) {
}
}
}
return line;
}
/**
* 不需要刘海屏的可以把下面到底的代码全部删掉,
* 上面和下面没有关联。
**/
/**
* 是否有刘海屏
*
* @return
*/
public static boolean hasNotchInScreen(Activity activity) {
// android P 以上有标准 API 来判断是否有刘海屏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
DisplayCutout displayCutout = activity.getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();
if (displayCutout != null) {
// 说明有刘海屏
return true;
}
} else {
// 通过其他方式判断是否有刘海屏 目前官方提供有开发文档的就 小米,vivo,华为(荣耀),oppo
String manufacturer = Build.MANUFACTURER;
if (TextUtils.isEmpty(manufacturer)) {
return false;
} else if (manufacturer.equalsIgnoreCase("HUAWEI")) {
return hasNotchHw(activity);
} else if (manufacturer.equalsIgnoreCase("xiaomi")) {
return hasNotchXiaoMi(activity);
} else if (manufacturer.equalsIgnoreCase("oppo")) {
return hasNotchOPPO(activity);
} else if (manufacturer.equalsIgnoreCase("vivo")) {
return hasNotchVIVO(activity);
} else {
return false;
}
}
return false;
}
/**
* 判断vivo是否有刘海屏
* https://swsdl.vivo.com.cn/appstore/developer/uploadfile/20180328/20180328152252602.pdf
*
* @param activity
* @return
*/
private static boolean hasNotchVIVO(Activity activity) {
try {
Class> c = Class.forName("android.util.FtFeature");
Method get = c.getMethod("isFeatureSupport", int.class);
return (boolean) (get.invoke(c, 0x20));
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 判断oppo是否有刘海屏
* https://open.oppomobile.com/wiki/doc#id=10159
*
* @param activity
* @return
*/
private static boolean hasNotchOPPO(Activity activity) {
return activity.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
}
/**
* 判断xiaomi是否有刘海屏
* https://dev.mi.com/console/doc/detail?pId=1293
*
* @param activity
* @return
*/
private static boolean hasNotchXiaoMi(Activity activity) {
try {
Class> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("getInt", String.class, int.class);
return (int) (get.invoke(c, "ro.miui.notch", 0)) == 1;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 判断华为是否有刘海屏
* https://devcenter-test.huawei.com/consumer/cn/devservice/doc/50114
*
* @param activity
* @return
*/
private static boolean hasNotchHw(Activity activity) {
try {
ClassLoader cl = activity.getClassLoader();
Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
return (boolean) get.invoke(HwNotchSizeUtil);
} catch (Exception e) {
return false;
}
}
}
不需要刘海屏的,可以直接去掉,两个没有关系的,只是不想再写个类了,就放在一起了。
之前拷贝的那个人的,他的代码在MIUISetStatusBarLightMode方法里的第二个dark判断处,是这么写的:
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
然后这次被发现了,小米的全面屏上出现了不是沉浸的了。出现了白色的状态栏,然后下面是占用状态栏的View,因为身边没有全面屏手机,用有全面屏的朋友找了半天,才发现这个问题....应该设置上全屏
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |View.SYSTEM_UI_FLAG_VISIBLE);