之前对于状态栏这块一直处于模糊状态,不是很清楚,实现方式也一直使用的之前很流行的SystemBarTintManager这个类库,后来遇到白底+黑字样式的状态栏,类似首页轮播、我的等一些页面要和状态栏融为一体,简单实现之后,在此记录一下,如果有那些地方不正确,还请指出,在此感谢,注:本文结合网上一些其他博客和资料,本文底部会给出相关参考链接。
**测试手机:魅族pro6s 7.1.1 ; 红米4A 6.0.1 ,三星GalaxyJ3 7.1.1
一:首先我们先实现状态栏和toolbar颜色一致的效果,效果如下:
代码如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0及以上
View decorView = activity.getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
this.getWindow().setStatusBarColor(getResources().getColor(R.color.colorPrimary));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4到5.0
WindowManager.LayoutParams localLayoutParams = activity.getWindow().getAttributes();
localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
}
setStatusTextColor(false,this);
在layout的根布局加上 android:fitsSystemWindows=”true” 即可,使设置的颜色与toolbar或者title布局的背景保持一致就可以了
代码很简单,具体各个Flag的意思,可自行百度,到处都是资料。下面我们来实现类似首页轮播和状态栏融为一体的效果,先看效果:
这里提一下,从6.0开始,状态栏文字颜色有深浅色调这么一说,可以设置View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR标记进行修改设置。相关代码如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0及以上
View decorView = activity.getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
}
setStatusTextColor(false,this);
这样设置之后会出现布局和状态栏重叠的问题,在第一种效果去掉android:fitsSystemWindows属性就会出现该问题,网上有很多解决方法,比如SystemBarTintManager类中就是通过add一个view的方式实现的,或者在布局中给合适的View添加一个padding或者margin,再或者放一个空布局隐藏显示等,fragment中同理,这里我们使用空布局隐藏显示的方法来实现,布局如下:
把id为layout_state_bar的View放到头部布局合适的位置,然后把该View的高度设置成状态栏的高度,获取方式有好几种,这里我们采取新建value方式,在value-19中加入:
<dimen name="status_bar_height">25dp</dimen>
在默认的value中加入:
<dimen name="status_bar_height">0dp</dimen>
代码如下
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
layout_state_bar.setVisibility(View.VISIBLE);
//获取到状态栏的高度
int statusHeight = getStatusBarHeight(this);
try {
//动态的设置隐藏布局的高度
if (layout_state_bar.getParent() instanceof LinearLayout) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) layout_state_bar.getLayoutParams();
params.height = statusHeight;
layout_state_bar.setLayoutParams(params);
} else if (layout_state_bar.getParent() instanceof RelativeLayout) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) layout_state_bar.getLayoutParams();
params.height = statusHeight;
layout_state_bar.setLayoutParams(params);
} else if (view.getParent() instanceof FrameLayout) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) layout_state_bar.getLayoutParams();
params.height = statusHeight;
layout_state_bar.setLayoutParams(params);
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "布局类型转换错误", Toast.LENGTH_LONG).show();
}
}
注:我这里layout_state_bar的父布局是LinearLayout,使用的时候要注意。
一般我们使列表布局滑动到一定具体会动态改变头部View的alpha和设置相关图标,这个时候,我们可以利用6.0中的SYSTEM_UI_FLAG_LIGHT_STATUS_BAR这个标记来实现,这里给出几个方法,代码如下:
/**
* 设置状态栏文字色值为深色调
*
* @param useDart 是否使用深色调
* @param activity
*/
public static void setStatusTextColor(boolean useDart, Activity activity) {
if (isFly()) {
processFlyMe(useDart, activity);
} else if (isMiUi()) {
processMIUI(useDart, activity);
} else {
if (useDart) {
setStatusDarkTextColor(activity);
} else {
setStatusTintTextColor(activity);
}
}
}
/**
* 深色(黑色字体)
*
* @param activity
*/
private static void setStatusDarkTextColor(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { //6.0
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
/**
* 浅色(白色字体)
*
* @param activity
*/
private static void setStatusTintTextColor(Activity activity) {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
通过调用setStatusTextColor()方法就可控制状态栏字体的颜色,代码中有一部分为适配小米和魅族的代码。
下面贴出代码:
/**
* 要求MiUi6以上 lightStatusBar为true时表示黑色字体,反之白色
*/
private static void processMIUI(boolean lightStatusBar, Activity activity) {
Class<? extends Window> clazz = activity.getWindow().getClass();
try {
int darkModeFlag;
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(), lightStatusBar ? darkModeFlag : 0, darkModeFlag);
} catch (Exception ignored) {
ignored.printStackTrace();
}
}
/**
* 要求FlyMe4以上 isLightStatusBar为true时表示黑色字体,反之白色
*/
private static void processFlyMe(boolean isLightStatusBar, Activity activity) {
WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
try {
Class<?> instance = Class.forName("android.view.WindowManager$LayoutParams");
int value = instance.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON").getInt(lp);
Field field = instance.getDeclaredField("meizuFlags");
field.setAccessible(true);
int origin = field.getInt(lp);
if (isLightStatusBar) {
field.set(lp, origin | value);
} else {
field.set(lp, (~value) & origin);
}
} catch (Exception ignored) {
ignored.printStackTrace();
}
}
注意,这里有个小米手机的深坑,真是坑,坑的不要不要的,小米开发版 7.7.13 及以后版本采用了系统的API,以上设置会不起作用,所以要修改一下,如下:
/**
* 要求MiUi6以上 lightStatusBar为true时表示黑色字体,反之白色
*/
private static void processMIUI(boolean lightStatusBar, Activity activity) {
Class<? extends Window> clazz = activity.getWindow().getClass();
try {
int darkModeFlag;
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(), lightStatusBar ? darkModeFlag : 0, darkModeFlag);
//开发版 7.7.13 及以后版本采用了系统API,旧方法无效但不会报错,所以两个方式都要加上
if (lightStatusBar) {
setStatusDarkTextColor(activity);
} else {
setStatusTintTextColor(activity);
}
} catch (Exception ignored) {
ignored.printStackTrace();
}
}
以上就是遇到的一些问题和主要实现代码,这里给出一个封装类,方便大家使用,如上述代码有错误之处,还请指出,再次感谢!!