/ 今日科技快讯 /
近日,国家计算机病毒中心发布了《移动APP违法违规问题及治理举措》。其中,MOMO陌陌、今日头条、京东金融、云闪付等下载量很高的应用也名列其中。
2016年至今,国家计算机病毒中心针对国内外的400多个应用发布渠道,共爬取移动应用APP总数量694万款,安全检测APP30515款,检测出恶意样本8000余款。
/ 作者简介 /
本篇文章来自Jimmy-Sun的投稿,分享了实现沉浸式状态栏的方方面面,相信会对大家有所帮助!同时也感谢作者贡献的精彩文章。
Jimmy-Sun的博客地址:
https://me.csdn.net/u013541140
/ 概述 /
现在市面上绝大多数APP都实现了沉浸式状态栏的效果,该效果可以极大地提升用户的使用体验。但是,APP默认的情况下只是设定一个固定的状态栏颜色,那么就需要我们通过代码去动态修改状态栏颜色的。那么,如何去实现呢?
首先来说,从Android 4.4开始才能实现沉浸式状态栏的,所以如果您的APP也支持Android 4.4以下版本,那还需要对Android 4.4以下版本做“不支持沉浸式状态栏”处理。
那么,从Android 4.4开始,大概可以分成三个阶段来实现沉浸式状态栏:
Android4.4(API 19) - Android 5.0(API 21):这个阶段的实现方式为:通过FLAG_TRANSLUCENT_STATUS设置状态栏为透明并且为全屏模式,然后通过添加一个与StatusBar一样大小的View,将View的背景设置为要设置的颜色,从而实现沉浸式。
Android 5.0(API 21) - Android 6.0(API 23):从Android 5.0开始,加入了一个重要的属性android:statusBarColor和方法setStatusBarColor(),通过这个方法我们就可以轻松实现沉浸式状态栏。但是在Android 6.0以下版本官方不支持设置状态栏的文字和图标颜色,目前只有小米和魅族的ROM提供了支持。
Android 6.0(API 23)以上版本:其实Android 6.0以上的实现方式和Android 5.0+ 是一样的,区别是从Android 6.0开始,官方支持改变状态栏的文字和图标的颜色。
/ 实现方案 /
为了实现沉浸式状态栏的效果,我们需要做一些前期工作,如下:
修改应用主题
为了更好地演示沉浸式状态栏的效果,我们修改应用的主题,使其不要显示Android默认的标题栏。打开styles.xml文件,可以改成如下代码,并且将colorPrimary等颜色设置删掉:
<style name='AppTheme' parent='Theme.AppCompat.Light.NoActionBar'></style>
获取状态栏高度
新建一个StatusBarUtils.java文件,在里面添加一个获取状态栏高度的方法,以后我们都会用的到这个方法。之后我们的核心代码也在这个工具类里实现。代码如下:
public class StatusBarUtils {
public static int getHeight(Context context) {
int statusBarHeight = 0;
try {
int resourceId = context.getResources().getIdentifier('status_bar_height', 'dimen',
'android');
if (resourceId > 0) {
statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
}
} catch (Exception e) {
e.printStackTrace();
}
return statusBarHeight;
}
}
public static int getHeight(Context context) {
int statusBarHeight = 0;
try {
int resourceId = context.getResources().getIdentifier('status_bar_height', 'dimen',
'android');
if (resourceId > 0) {
statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
}
} catch (Exception e) {
e.printStackTrace();
}
return statusBarHeight;
}
}
下面我们就按照从高版本到低版本的顺序来讲解如何更优雅地实现沉浸式状态栏。
/ Android 5.0+ /
设置状态栏颜色
在StatusBarUtils类里添加如下方法,实现设置状态栏颜色的功能:
public static void setColor(@NonNull Window window, @ColorInt int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.setStatusBarColor(color);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.setStatusBarColor(color);
}
}
修改状态栏颜色的功能其实就是对Window进行操作,而该Window可以是Activity或Dialog等持有的Window,所以我们就封装了一个传递Window的方法。为了便于对Activity直接操作,可以再增加一个如下方法:
public static void setColor(Context context, @ColorInt int color) {
if (context instanceof Activity) {
setColor(((Activity) context).getWindow(), color);
}
}
if (context instanceof Activity) {
setColor(((Activity) context).getWindow(), color);
}
}
下面测试一下,新建一个Activity,将其布局背景设置为某个颜色,例如主题色,布局代码如下:
<LinearLayout xmlns:android='http://schemas.android.com/apk/res/android'
android:layout_width='match_parent'
android:layout_height='match_parent'
android:orientation='vertical'
android:background='@color/colorPrimaryDark'>
</LinearLayout>
在没设置状态栏颜色时,展示效果如下:

接下来在Activity的onCreate()方法里调用设置状态栏颜色的方法,代码如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_color);
StatusBarUtils.setColor(this, getResources().getColor(R.color.colorPrimaryDark));
}
展示效果如下:

这样状态栏和内容的颜色就可以一样啦!
设置状态栏文字颜色
下面我们把背景和状态栏颜色改成纯绿色(#00FF00),看看效果:

发现颜色好亮啊,状态栏里的文字都看不清了。在这种情况下,我们是可以将状态栏文字的颜色改成深色的,官方也仅支持设置状态栏文字和图标的深色模式和浅色模式,但是官方仅在Android 6.0以上版本提供支持。设置代码如下:
private static void setTextDark(Window window, boolean isDark) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
View decorView = window.getDecorView();
int systemUiVisibility = decorView.getSystemUiVisibility();
if (isDark) {
decorView.setSystemUiVisibility(systemUiVisibility | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
decorView.setSystemUiVisibility(systemUiVisibility & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
}
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
View decorView = window.getDecorView();
int systemUiVisibility = decorView.getSystemUiVisibility();
if (isDark) {
decorView.setSystemUiVisibility(systemUiVisibility | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
} else {
decorView.setSystemUiVisibility(systemUiVisibility & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
}
同样再增加一个对Activity的支持:
public static void setTextDark(Context context, boolean isDark) {
if (context instanceof Activity) {
setTextDark(((Activity) context).getWindow(), isDark);
}
}
if (context instanceof Activity) {
setTextDark(((Activity) context).getWindow(), isDark);
}
}
为了能够根据状态栏背景颜色的深浅而自动设置文字的颜色,我们再新增一个判断颜色深浅的方法:
public static boolean isDarkColor(@ColorInt int color) {
return ColorUtils.calculateLuminance(color) < 0.5;
}
return ColorUtils.calculateLuminance(color) < 0.5;
}
然后在setColor()方法里新增一行设置状态栏文字颜色的代码,如下:
public static void setColor(@NonNull Window window, @ColorInt int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.setStatusBarColor(color);
setTextDark(window, !isDarkColor(color));
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
window.setStatusBarColor(color);
setTextDark(window, !isDarkColor(color));
}
}
运行一下,就可以看到效果了:






































苏公安网备 32011402010933号