700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 安卓动态修改系统状态栏背景和文字颜色 以及动态显示或隐藏系统状态栏

安卓动态修改系统状态栏背景和文字颜色 以及动态显示或隐藏系统状态栏

时间:2021-11-16 06:34:05

相关推荐

安卓动态修改系统状态栏背景和文字颜色 以及动态显示或隐藏系统状态栏

关于动态修改系统状态栏背景、字体和图标颜色,以及动态显示或隐藏系统状态栏,一直都是都是许多项目的常规需求。但是,由于不同版本间的兼容性差异,网上的实现方法多种多样。并且,许多方法都会存在这样、那样的不足。使用麻烦不说,一不小心还会产生各种异常,令人得不偿失。

这里,我们希望使用一个统一、简洁的方法,实现一键修改系统状态栏背景和文字颜色。以及动态的控制系统状态栏的显示或隐藏。

知识储备:安卓在5.0之前,并没有提供可以修改系统状态栏背景色的方法,而在6.0之前,也没有提供修改状态栏文字和图标颜色的方法。另外,国内某些厂商,如小米、魅族等修改了官方API,可能导致修改方法无效等。

因此,要想修改系统状态栏背景色,我们需要系统在5.0以上,而需要修改状态栏文字和图标颜色,则需要系统在6.0以上。这里建议向上兼容,即只有系统在6.0以上才允许动态修改系统状态栏,否则如果5.0的设备将状态栏北京改为白色,而字体颜色无法修改,默认也是白色。那就无法看见了。好在随着安卓系统的不断更新,目前6.0以上系统的覆盖率已经达到90%以上,所以即使无法做到完全覆盖,我们也可以确保绝大部分的用户体验。

下面是具体方案:

1.设置状态栏的背景颜色

// 设置状态栏底色颜色getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);getWindow().setStatusBarColor(parseColor);

方法非常简单,这个背景色可以设置为任意颜色值,并且可以在任何时刻修改。需要注意的是API必须是5.0以上才有用哦。

2.设置状态栏文字和图标颜色

文字和图标颜色并不能设置为任意颜色,他只有两种选择:亮色系(文字和图标颜色为黑灰色)和暗色系(文字和图标颜色为白色)

根据我们设置的状态栏背景色,我们需要动态修改文字和图标颜色,以保证它们能被看清。例如,当背景色为白色时,我们采用亮色系,当背景色为黑色时,我们采用暗色系。那么问题来了,我的程序怎么知道这个时候该采用哪种色系呢?如果靠人工判断那也太麻烦了。

别慌,官方为我们提供了一个判断方法:

ColorUtils.calculateLuminance(parseColor)

返回值的取值范围为0.0-1.0 当大于0.5时,我们就可以认为当前颜色为亮色系,需要将文字和图标颜色设置为黑灰色;反之,则将文字和图标颜色设置为白色。设置的方法也非常简单:

window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);//亮色系,将文字和图标颜色设置为黑灰色

window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);//暗色系,将文字和图标颜色设置为白色

这下就大功告成了吗?别急,上面我们说了国内某些厂商,如小米、魅族等修改了官方API,我们会发现这两个方法在小米和魅族的部分机型上会显示无效果。需要针对性的做出兼容处理。

//小米手机兼容处理,修改系统状态栏文字和图标颜色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;} catch (Exception e) {}

//魅族手机兼容处理,修改系统状态栏文字和图标颜色

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) {}

这是网上找到的修改方法,亲测好用。

那么,我们的完整动态修改系统状态栏背景和文字颜色方法如下:

/*设置状态栏颜色和文字颜色,小米,魅族需要自定义,比较坑爹*/public static void setColor(Window window, int parseColor) {// 操作系统的api版本大于21,才能改变状态栏的颜色,api版本大于23,才能改变状态栏文字颜色if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {try {// 设置状态栏底色颜色window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);window.setStatusBarColor(parseColor);// 如果亮色,设置状态栏文字为黑色boolean dark = ColorUtils.calculateLuminance(parseColor) >= 0.5;if(MIUISetStatusBarLightMode(window,dark)){//小米的设置成功/*Logger.e("setColor","小米手机,设置成功");*/}else if(FlymeSetStatusBarLightMode(window,dark)){//魅族的设置成功/*Logger.e("setColor","魅族手机,设置成功");*/}else{if (ColorUtils.calculateLuminance(parseColor) >= 0.5) {window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);} else {window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);}}} catch (Exception e) {e.printStackTrace();}}}/*** 小米MIUI系统 亲测好用** @param window* @param dark* @return*/public static boolean MIUISetStatusBarLightMode(Window window, boolean dark) {boolean result = false;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;} catch (Exception e) {}}return result;}/*** 设置状态栏图标为深色和魅族特定的文字风格* 可以用来判断是否为Flyme用户** @param window 需要设置的窗口* @param dark 是否把状态栏字体及图标颜色设置为深色* @return boolean 成功执行返回true*/public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {boolean result = false;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;}

建议将以上方法放到你的工具类里,具体界面调用时只需一行代码就可以搞定了。

ToolsUtil.setColor(mContext.getWindow(), Color.WHITE);

至于动态控制系统状态栏的显示或隐藏。也很简单:

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN);//隐藏状态栏

动态显示状态栏直接用上面提到的的ToolsUtil.setColor方法,就可以一并实现了。

补充PS:至于网上说的那种沉浸式状态栏,由于需要调整布局,所以使用起来没这么简单,建议如非必要,不要这么做。具体方法给出如下:

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);//设置沉浸模式getWindow().setStatusBarColor(Color.TRANSPARENT);//设置状态栏背景透明//需要调整布局,为状态栏显示预留出空间

再次补充PS:还有一种随滑动手势实现状态栏颜色渐变的需求,本文没有提到。不过谷歌已经提供了很好的解决方案,CoordinatorLayout,有兴趣的可以自行百度一下。本文不做细讲,我们只说一下,什么时候去修改状态栏里的文字和图标颜色。

我们只需要监听AppBarLayout的onOffsetChanged(AppBarLayoutappBarLayout, int verticalOffset)方法,根据偏移量verticalOffset的值,动态设定状态栏里的文字和图标颜色即可。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。