Android实现修改状态栏背景、字体和图标颜色的方法
前言:
android开发,对于状态栏的修改,实在是不友好,没什么api可以用,不像ios那么方便.但是ui又喜欢只搞ios一套.没办法.各种翻源码,写反射.真的蛋疼.
需求场景:
当toolbar及状态栏需要为白色或浅色时(如简书),状态栏由于用的light风格theme,字体,图标也都是白色,会看不清.如果改变成黑色就很和谐了.
一.修改状态栏颜色:
改变状态栏颜色,可以看看这篇文章.传送门:
传送门实现的效果:
这种方法实现的状态栏变色,没有黑色背景.
使用全屏模式实现的效果如下(qq的效果):
很明显的黑色背景.
我用的手机是华为,系统7.0
二.修改状态栏字体:
通用工具类:
public class statusbarutil { /** * 设置状态栏黑色字体图标, * 适配4.4以上版本miuiv、flyme和6.0以上版本其他android * * @return 1:miuui 2:flyme 3:android6.0 */ public static int getstatusbarlightmode(window window) { int result = 0; if (build.version.sdk_int >= build.version_codes.kitkat) { if (miuisetstatusbarlightmode(window, true)) { result = 1; } else if (flymesetstatusbarlightmode(window, true)) { result = 2; } else if (build.version.sdk_int >= build.version_codes.m) { window.getdecorview().setsystemuivisibility(view.system_ui_flag_light_status_bar); result = 3; } else {//5.0 } } return result; } /** * 已知系统类型时,设置状态栏黑色字体图标。 * 适配4.4以上版本miuiv、flyme和6.0以上版本其他android */ public static void setstatusbarlightmode(window window) { int type = getstatusbarlightmode(window); if (type == 1) { miuisetstatusbarlightmode(window, true); } else if (type == 2) { flymesetstatusbarlightmode(window, true); } else if (type == 3) { window.getdecorview().setsystemuivisibility(view.system_ui_flag_light_status_bar); } else {//5.0 } } /** * 清除miui或flyme或6.0以上版本状态栏黑色字体 */ public static void statusbardarkmode(window window) { int type = getstatusbarlightmode(window); if (type == 1) { miuisetstatusbarlightmode(window, false); } else if (type == 2) { flymesetstatusbarlightmode(window, false); } else if (type == 3) { window.getdecorview().setsystemuivisibility(view.system_ui_flag_visible); } } /** * 设置状态栏图标为深色和魅族特定的文字风格 * 可以用来判断是否为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; } /** * 设置状态栏字体图标为深色,需要miuiv6以上 * * @param window 需要设置的窗口 * @param dark 是否把状态栏字体及图标颜色设置为深色 * @return boolean 成功执行返回true */ 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; } }
activity中使用:
statusbarutil.setstatusbarlightmode(getwindow());
效果:
出现的问题:
1.statusbar背景色变成了colorprimarydark默认颜色,但是我的配置是白色背景(具体配置代码见最后).
分析原因:
setsystemuivisibility()会刷新view的属性配置.由于statusbar默认使用colorprimarydark属性.所以颜色会变回默认颜色
此时步骤一设置背景的方法就会失效.
private void initstatusbar() { if (statusbarview == null) { int identifier = getresources().getidentifier("statusbarbackground", "id", "android"); statusbarview = getwindow().findviewbyid(identifier); } if (statusbarview != null) { statusbarview.setbackgroundresource(mvpconfig.statusdrawable); } }
原因:当传入的resid相同时,就不会再次去设置背景色.
解决办法:
private void initstatusbar() { if (statusbarview == null) { int identifier = getresources().getidentifier("statusbarbackground", "id", "android"); statusbarview = getwindow().findviewbyid(identifier); } if (statusbarview != null) { statusbarview.setbackgrounddrawable(null);//在设置前将背景设置为null; statusbarview.setbackgroundresource(mvpconfig.statusdrawable); } }
修改后的效果:
三.完整代码:
1.mvpconfig
public class mvpconfig { public static int statusdrawable; public static int toolbarbackgroundcolor; public static int toolbarbackgrounddrawable; public static int backdrawable; public static boolean isstatusbarlight; public static void setstatusbardrawable(@drawableres int statusdraw) { statusdrawable = statusdraw; } public static boolean isstatusbar() { return statusdrawable > 0; } public static void settoolbardrawable(int toolbarbackgrounddrawable) { mvpconfig.toolbarbackgrounddrawable = toolbarbackgrounddrawable; } public static void setbackdrawable(int backdrawable) { mvpconfig.backdrawable = backdrawable; } public static void setisstatusbarlight(boolean isstatusbarlight) { if (build.version.sdk_int <= build.version_codes.lollipop_mr1) { mvpconfig.statusdrawable = color.parsecolor("#33ffffff"); } mvpconfig.isstatusbarlight = isstatusbarlight; }
2.application中
@override public void oncreate() { super.oncreate(); mvpconfig.settoolbardrawable(r.color.white); mvpconfig.setstatusbardrawable(r.color.white); mvpconfig.setbackdrawable(r.drawable.back); mvpconfig.setisstatusbarlight(true); }
3.baseactivity
@override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); //延时加载数据. looper.myqueue().addidlehandler(new messagequeue.idlehandler() { @override public boolean queueidle() { if (isstatusbarlight()) { statusbarutil.setstatusbarlightmode(getwindow()); } if (isstatusbar()) { initstatusbar(); getwindow().getdecorview().addonlayoutchangelistener(new view.onlayoutchangelistener() { @override public void onlayoutchange(view v, int left, int top, int right, int bottom, int oldleft, int oldtop, int oldright, int oldbottom) { initstatusbar(); } }); } mpresenter.initdata(); return false; } }); } private void initstatusbar() { if (statusbarview == null) { int identifier = getresources().getidentifier("statusbarbackground", "id", "android"); statusbarview = getwindow().findviewbyid(identifier); } if (statusbarview != null) { if (isstatusbarlight()) { statusbarview.setbackgrounddrawable(null); } statusbarview.setbackgroundresource(mvpconfig.statusdrawable); } } //子类通过复写该方法,控制是否改变statusbar protected boolean isstatusbar() { return mvpconfig.isstatusbar(); } //子类通过复写该方法,控制是否需要改变statusbar字体颜色 protected boolean isstatusbarlight() { return mvpconfig.isstatusbarlight; }
四.补充:
6.0以下,5.0原生系统无法修改字体颜色,用了个比较取巧的办法,设置成半透明灰色.
public static void setstatusbarlightmode(window window) { int type = getstatusbarlightmode(window); if (type == 1) { miuisetstatusbarlightmode(window, true); } else if (type == 2) { flymesetstatusbarlightmode(window, true); } else if (type == 3) { window.getdecorview().setsystemuivisibility(view.system_ui_flag_light_status_bar); } else { //5.0 if (build.version.sdk_int <= build.version_codes.lollipop_mr1) { mvpconfig.statusdrawable = color.parsecolor("#33ffffff"); } } }
由于是直接修改window中的statusbarview的背景,而frgament依赖于activity,所以在activity与fragment直接跳转时,状态栏不是很适用.比如:activity是蓝色,fragment需要是白色,fragment需要通过window修改状态栏颜色.有点麻烦.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。