1 .FitsSystemWindows和ClipToPadding联合运用
我们找到DecroView中的id为content的Framelayout,添加一个高度为statusBar高度的控件,然后调用下面方法
/*** 设置根布局参数*/private static void setRootView(Activity activity) {ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content);for (int i = 0, count = parent.getChildCount(); i < count; i++) {View childView = parent.getChildAt(i);if (childView instanceof ViewGroup) {//调用此方法系统会默认设置paddingTop,由于调用此方法之前add了一个paddingTop高度的view用于沉浸式状态栏childView.setFitsSystemWindows(true);//不影响滑动效果(如ListView)(滑动区还是整个view,不设置会缺少上面的paddingTop)((ViewGroup) childView).setClipToPadding(true);}}}
2.在普通布局文件中添加一个View,在代码中动态改变高度,把它变成statusBar高度,不需要设置FitsSystemWindows,这种方法侵入性更高,不推荐使用
方法1中的完整方法如下:
private static final int FAKE_STATUS_BAR_VIEW_ID = R.id.statusbarutil_fake_status_bar_view;/*** 设置状态栏颜色** @param activity 需要设置的activity* @param color 状态栏颜色值* @param statusBarAlpha 状态栏透明度*/public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);if (fakeStatusBarView != null) {if (fakeStatusBarView.getVisibility() == View.GONE) {fakeStatusBarView.setVisibility(View.VISIBLE);}fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));} else {decorView.addView(createStatusBarView(activity, color, statusBarAlpha));}setRootView(activity);}}/*** 计算状态栏颜色** @param color color值* @param alpha alpha值* @return 最终的状态栏颜色*/private static int calculateStatusColor(@ColorInt int color, int alpha) {if (alpha == 0) {return color;}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;}/*** 设置根布局参数*/private static void setRootView(Activity activity) {ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content);for (int i = 0, count = parent.getChildCount(); i < count; i++) {View childView = parent.getChildAt(i);if (childView instanceof ViewGroup) {//调用此方法系统会默认设置paddingTop,由于调用此方法之前add了一个paddingTop高度的view用于沉浸式状态栏childView.setFitsSystemWindows(true);//不影响滑动效果(如ListView)(滑动区还是整个view,不设置会缺少上面的paddingTop)((ViewGroup) childView).setClipToPadding(true);}}}/*** 生成一个和状态栏大小相同的半透明矩形条** @param activity 需要设置的activity* @param color 状态栏颜色值* @param alpha 透明值* @return 状态栏矩形条*/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));statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID);return statusBarView;}
<?xml version="1.0" encoding="utf-8"?>
<resources><item type="id" name="statusbarutil_fake_status_bar_view" /><item type="id" name="statusbarutil_translucent_view" />
</resources>
另外,如果我们想要修改状态栏的字体颜色和图标颜色,需要安卓6.0以上版本或者小米和魅族等部分厂商可以修改,6.0可以在主题中设置
<item name="android:windowLightStatusBar">true</item>
只有两种模式,true字体是深色和false是浅色