Android状态栏着色(非沉浸式状态栏)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android状态栏着色(非沉浸式状态栏)相关的知识,希望对你有一定的参考价值。

参考技术A 由于产品需求 , 要将一级页面的5个Fragment设置不一样颜色的状态栏; 然后我对着网上的博文抄了一遍 ,发现兼容问题很差 , 要么就是顶部的状态栏没有实现全屏 , 要么就是底部的虚拟按钮遮挡导航栏(华为手机和小米手机), 最后自定义主题和设置xml布局顶部高度来解决了这个问题;
解决方案:

第一步.在values的styles中自定义主题:

第二步.创建values-v19文件夹和styles.xml:

第三步.创建values-v21文件夹和styles.xml:

第三步.引用主题:

第四步.Fragment 状态栏填充颜色:(如果一节界面的头部是轮播图直接预留20dp的高度)
不设置预留高度,状态栏会和toolbar叠加在一起 (状态栏在toolbar上方)

运行后效果图如下:

轮播图在顶部的时候直接预留状态栏的高度即可:

指定颜色的界面设置多一层有颜色的View:

Android 沉浸式(透明)状态栏细研-超级细还附 Demo

前言

在 Android 4.4 中引入了沉浸模式的功能,但这个版本非真正的沉浸模式,应该说是透明模式。Android 5.0 以后才可以在系统层面实现真正的沉浸式状态栏。
沉浸式状态栏是为了与当前使用的 App 页面风格统一,不会显的那么突兀,保持友好且一致的用户体验而设计,是现在主流 App 必备的适配内容。今天我们就细细的研究一下沉浸式状态栏的适配。

先看效果

实现的功能

  • 真透明状态栏(个别机型无法适配全透明,如锤子)
  • 动态改变 ToolBar 或者自定义的 TitleBar 颜色,修改背景色即可,不需要动态改变状态栏颜色
  • 状态栏主题模式(黑/白色)切换
  • 修复适配 DrawerLayout 在 4.4 上白边的问题
  • 适配“刘海屏”上的沉浸式状态栏
  • 导航栏实现个人认为美观并通配的配色,可自定义修改

看实现代码

状态栏设置为透明

/**
 * 设置透明StatusBar
 *
 * @param activity Activity
 */
private static void setTranslucentStatusBar(Activity activity) 
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) 
        return;
    
    Window window = activity.getWindow();
    //透明状态栏
    window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
        //5.0及以上版本,创建 Navigation Bar
        createNavBar(activity);
     else 
        //4.4 版本设置为透明状态栏
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    

切换状态栏主题

这里主要是为了更好的适配页面背景,因为有的页面适合白色的状态栏图标,有的适合黑色的状态栏图标

/**
 * Android 6.0使用原始的主题适配
 *
 * @param activity Activity
 * @param darkMode 是否是黑色模式
 */
public static void setBarDarkMode(Activity activity, boolean darkMode) 
    Window window = activity.getWindow();
    if (window == null) 
        return;
    
    //设置StatusBar模式
    if (darkMode) //黑色模式
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) //设置statusBar和navigationBar为黑色
                window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
             else //设置statusBar为黑色
                window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            
        
     else //白色模式
        int statusBarFlag = View.SYSTEM_UI_FLAG_VISIBLE;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
            statusBarFlag = window.getDecorView().getSystemUiVisibility()
                & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
        
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) //设置statusBar为白色,navigationBar为灰色
            //                int navBarFlag = window.getDecorView().getSystemUiVisibility()
            //                        & ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;//如果想让navigationBar为白色,那么就使用这个代码。
            int navBarFlag = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
            window.getDecorView().setSystemUiVisibility(navBarFlag | statusBarFlag);
         else 
            window.getDecorView().setSystemUiVisibility(statusBarFlag);
        
    
    setHuaWeiStatusBar(darkMode, window);

白色黑色

设置 Navigation Bar 配色

现在是全面屏手机了,但是也可以设置开启虚拟导航栏的。这里主要是更改 Navigation Bar 在不同 Android 版本的配色,这里可以根据设计师的配色或者分装成接口使用。

/**
 * 创建Navigation Bar
 *
 * @param activity 上下文
 */
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static void createNavBar(Activity activity) 
    int navBarHeight = getNavigationBarHeight(activity);
    int navBarWidth = getNavigationBarWidth(activity);
    if (navBarHeight > 0 && navBarWidth > 0) 
        //创建NavigationBar
        View navBar = new View(activity);
        FrameLayout.LayoutParams pl;
        if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) 
            pl = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, navBarHeight);
            pl.gravity = Gravity.BOTTOM;
         else 
            pl = new FrameLayout.LayoutParams(navBarWidth, ViewGroup.LayoutParams.MATCH_PARENT);
            pl.gravity = Gravity.END;
        
        navBar.setLayoutParams(pl);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) 
            navBar.setBackgroundColor(Color.parseColor("#fffafafa"));
         else 
            navBar.setBackgroundColor(Color.parseColor("#40000000"));
        
        //添加到布局当中
        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
        decorView.addView(navBar);
        //设置主布局PaddingBottom
        ViewGroup contentView = decorView.findViewById(android.R.id.content);
        if (activity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) 
            contentView.setPaddingRelative(0, 0, 0, navBarHeight);
         else 
            contentView.setPaddingRelative(0, 0, navBarWidth, 0);
        

    

修复 DrawerLayout 顶部白边的问题

在实际项目中我们可能会用到 DrawerLayout ,但是设置了透明状态栏后,在 Android 4.4 上会出现顶部白边的问题,通过下面的方法可修复

/**
 * 设置 DrawerLayout 在4.4版本下透明,不然会出现白边
 *
 * @param drawerLayout DrawerLayout
 */
public static void setTranslucentDrawerLayout(DrawerLayout drawerLayout) 
    if (drawerLayout != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) 
        drawerLayout.setFitsSystemWindows(true);
        drawerLayout.setClipToPadding(false);
    

到这里我们已经看到了实现的核心方法,我已经封装了一个 AndroidBarUtils ,方便项目中使用可以,下面我们介绍一下如何使用,并且你可以直接查看我编写好的 GitHub wiki

使用方法

如何引用?

暂时不提供远程库引用的方式,只有一个类,点击下载 然后放到项目中即可,也方便自己扩展。

调用方法

  • 设置透明状态栏
AndroidBarUtils.setTranslucent(this);
  • 修复重叠问题以及适配“刘海屏”(ToolBar、自定义的TitleBar、NavigationView 都可用)
//ToolBar、自定义的TitleBar 重叠问题以及适配刘海屏
AndroidBarUtils.setBarPaddingTop(this, view);
  • 设置状态栏主题(6.0及以上才有效果)
//false:白色 true:黑色
AndroidBarUtils.setBarDarkMode(this, false);

不常见问题

  • Android 4.4 上使用了 DrawerLayout 会出现白条,如何解决?
AndroidBarUtils.setTranslucentDrawerLayout(drawerLayout);
  • 如何让 NavigationView 适配 刘海屏
AndroidBarUtils.setBarPaddingTop(this,navigationView.getHeaderView(0));

最终效果

源码仓库

总结

本文我们为了优化用户的 App 使用体验,一起查看了 Android 各个版本上沉浸式(透明)状态栏的实现细节,并适配了黑白状态栏主题以及 DrawerLayoutNavigationView 的异常情况。虽然是很小的一个优化的点,但是从页面美观和体验角度做了很大的提升。

参考:

关于我

  • 15 年~18 年,使用 Android 原生做智能硬件相关的 App 研发
  • 18 年 5 月,一次偶然的机会接触到了 Flutter ,然后开始自学,可以看 weather_flutter 是我练习 Flutter 的入门实战项目(我现在依然觉得他非常适合 Flutter 入门练习使用)
  • 18 年 8 月,顶着巨大的压力(Flutter 当时还没有 Release 1.0)开始使用 Flutter 开发企业级项目,并且开发维护了十几个 Flutter 插件包(因为当时插件资源非常的匮乏)
  • 截止目前主导并参与上线了 4 款企业级Flutter App,当前正在负责的一款 App 累计用户 120W+,使用 Flutter 得到了极佳的体验

👏 欢迎点赞➕收藏➕分享,有任何问题随时在下面👇评论,我会第一时间回复哦

以上是关于Android状态栏着色(非沉浸式状态栏)的主要内容,如果未能解决你的问题,请参考以下文章

Android---沉浸式状态栏

Android状态栏着色

Android中沉浸式状态栏的应用

Android 沉浸式状态栏

Android 沉浸式(透明)状态栏细研-超级细还附 Demo

如何实现Android沉浸式状态栏