欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现修改状态栏背景、字体和图标颜色的方法

程序员文章站 2023-12-19 16:02:28
前言: android开发,对于状态栏的修改,实在是不友好,没什么api可以用,不像ios那么方便.但是ui又喜欢只搞ios一套.没办法.各种翻源码,写反射.真的蛋疼....

前言:

android开发,对于状态栏的修改,实在是不友好,没什么api可以用,不像ios那么方便.但是ui又喜欢只搞ios一套.没办法.各种翻源码,写反射.真的蛋疼.

需求场景:

当toolbar及状态栏需要为白色或浅色时(如简书),状态栏由于用的light风格theme,字体,图标也都是白色,会看不清.如果改变成黑色就很和谐了.

一.修改状态栏颜色:

改变状态栏颜色,可以看看这篇文章.传送门:

传送门实现的效果:

这种方法实现的状态栏变色,没有黑色背景.

Android实现修改状态栏背景、字体和图标颜色的方法

使用全屏模式实现的效果如下(qq的效果):

Android实现修改状态栏背景、字体和图标颜色的方法

很明显的黑色背景.

我用的手机是华为,系统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());

效果:

Android实现修改状态栏背景、字体和图标颜色的方法

出现的问题:

1.statusbar背景色变成了colorprimarydark默认颜色,但是我的配置是白色背景(具体配置代码见最后).

分析原因:

setsystemuivisibility()会刷新view的属性配置.由于statusbar默认使用colorprimarydark属性.所以颜色会变回默认颜色

Android实现修改状态栏背景、字体和图标颜色的方法

此时步骤一设置背景的方法就会失效.

  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相同时,就不会再次去设置背景色.

Android实现修改状态栏背景、字体和图标颜色的方法

解决办法:

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

修改后的效果:

Android实现修改状态栏背景、字体和图标颜色的方法

三.完整代码:

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修改状态栏颜色.有点麻烦.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: