Android 自动取色并设置沉浸式状态栏 - Stars-One的杂货小窝

最近在进行产品的优化,也是研究了下沉浸式状态栏的实现方法及自动取色,记录一下笔记

设置沉浸式状态栏

1.添加依赖

这里,是使用了一个Android的工具开源库来实现了功能,首先需要依赖

// Android的工具类   https://github.com/Blankj/AndroidUtilCode/blob/master/lib/utilcode/README-CN.md
implementation 'com.blankj:utilcodex:1.31.0'

2.使用

工具类中有个BarUtils的类,里面提供了对应状态栏和导航栏的对应方法,如设置透明状态栏,设置状态栏颜色等

下面,我们就是用到其中的setStatusBarColor()方法

APP的原图为这样

我们下面需要设置沉浸式的状态栏

使用以下方法:

BarUtils.setStatusBarColor(this, ColorUtils.getColor(R.color.design_default_color_primary))

ColorUtils也是工具库中的一个工具类,通过它可以拿到定义到color.xml中的方法

我们可以看到,颜色是变了,但是布局似乎被ActionBar遮挡住了一部分

这个时候有以下的解决方法:

在你的Activity对应的布局中加上android:fitsSystemWindows="true"的属性即可解决

如下图所示

当然,这样做的话会比较繁琐,我们可以考虑使用代码的方式来设置

val contentParent = findViewById(android.R.id.content)
contentParent.getChildAt(0).fitsSystemWindows = true

效果就出来了:

但细看的话,觉得还是看出ActionBar的边界,我们可以考虑使用setStatusBarColor()另一个参数方法

BarUtils.setStatusBarColor(this, ColorUtils.getColor(R.color.design_default_color_primary),true)

效果比之前的要好些:

实际上,这个的传参的isDecor代表了两种实现沉浸式状态栏的方法

  • true,则是往DecorView添加状态栏,
  • false,则是往ContentView中添加状态栏

所以,这里我个人是比较推荐DecorView,因为显示的效果比较好

3.补充-主题为NoActionBar被遮挡问题解决

在设置主题为NoActionBar之后,会发现出现下面的情况

其实解决方法如上述一样,只要设置android:fitsSystemWindows="true"或者用代码去设置即可解决,这里不再赘述

设置状态栏亮色或暗色图标

上面,我们只是设置了状态栏的颜色,但是没有设置对应的显示图标,如果你状态栏设置的颜色比较亮的话,这个时候为了方便图标显示,你得将图标变为暗色的图标

那么具体要怎么实现呢?

其实BarUtil还是有提供对应的方法

val color = ColorUtils.getColor(R.color.design_default_color_primary)
BarUtils.setStatusBarColor(this, color) //设置状态栏图标是否为亮色图标
BarUtils.setStatusBarLightMode(this, ColorUtils.isLightColor(color))

这里,我们需要判断下颜色是否为亮色,怎么判断呢?

我们上述引用的库中,带有一个工具类ColorUtils,可以通过其isLightColor()方法来判断颜色是否亮色

于是我们两个方法结合起来,就是上面的设置的方法了

PS:如果想要实现导航条颜色也需要变换,可以使用此方法setNavBarColor(),如下代码:

BarUtils.setNavBarColor(this,color)

自动取色

1.添加依赖

自动取色这里是用到了另外一个开源库palette

这个是谷歌官方出的一个库,主要是用来发布获取图片的主色调

implementation 'androidx.palette:palette:1.0.0'

//如果是Kotlin,推荐使用这个
implementation 'androidx.palette:palette-ktx:1.0.0'

下面我是Kotlin使用进行说明

2.使用

Palette是从图片Bitmap中进行颜色提取,所以需要我们传一个图片

这里,我们可以直接将当前屏幕的截图Bitmap对象拿到,然后通过Palette去提取对应的颜色特征点即可

截图:

//截图
val drawingCache = ScreenUtils.screenShot(this)

ScreenUtils还是上述工具类库中的工具类,方便获取截图Bitmap对象

Plaette用法:

Palette.from(drawingCache).generate {
//具体获得到的颜色特征数据 }

实际上,如果不设置如何参数,上述就可以取颜色特征点了,Palette会开启异步线程来执行解析操作,并将最终结果回调到Lambda表达式当中

具体的颜色提取算法是由Palette自己控制的,我们无需关心。反正只需要知道,最终提取出来的这些颜色值都是这个bitmap的指定区域里最具代表性的就可以了。

一般来说,还是推荐设置对应的参数

比如说我们的需求,是要动态取色,那么,这个颜色应该怎么样才比较准确呢?

那当然是直接取状态栏下方的页面数值,这样就比较好的有着沉浸式效果了

那么,这个需要我们就可以setRegion()方法来指定解析这个bitmap对象的哪个区域,其他区域的颜色值对我们来说没有意义

当然,除此之外,我们调用maximumColorCount()方法来告诉Palette一共需要提取多少个颜色特征点。

于是,代码就变为以下:

//先截图,取当前截图的主要色调
val drawingCache = ScreenUtils.screenShot(this) Palette.from(drawingCache).maximumColorCount(5).generate {
//取色成功后的异步回调,取主色调
it?.let {
val swatches = it.swatches
//便利找寻主色调
var mostSwatch :Palette.Swatch?=null
swatches.forEach {
if (mostSwatch != null) {
//population指的是出现最多的颜色
if (mostSwatch!!.population < it.population) {
mostSwatch = it
}
} else {
mostSwatch = it
}
} //设置状态栏为主色调
mostSwatch?.let {
val color = it.rgb
BarUtils.setStatusBarColor(this, color, true)
BarUtils.setStatusBarLightMode(this, ColorUtils.isLightColor(color)) val contentParent: ViewGroup = findViewById(android.R.id.content)
contentParent.getChildAt(0).fitsSystemWindows = true
} }
}

原理研究

这里,稍微总结下看到的相关知识原理,不追求长篇大论,各位要深入了解可自行搜索资料

关于Activity页面层级问题

首先,我们要了解下对应的层级关系图,如下图所示:

上述图中,DecorView其实是继承FrameLayout,然后其中包裹一个子View

这个子View是LinearLayout,方向为竖直方向,其内有两个FrameLayout

沉浸式状态栏实现原理

沉浸式状态栏主要实现思路:先将原先的状态栏设置为透明色,之后在父布局一个View来代替状态栏的占位(高度与状态栏的高度一致)

这里的父布局有两种情况,一种是在DecorView中新增一个新的View来代替状态栏的占位,另外一种则是在ContentView中(通过android.R.id.content可以找到)添加View

如果是第二种方法,因为在不同版本中,此布局包含的子View有所区别,所以在高版本会出现状态栏被遮挡的情况

上述这句总结还未验证过,如果说错可以希望在评论区指出

这个时候可以通过设置fitsSystemWindows进行解决

关于fitsSystemWindows属性

上面也是提到了使用android:fitsSystemWindows="true"解决布局状态栏被遮挡问题,实际上,这个属性只是个标识属性,具体要对应的布局去实现

上面意思呢?就比如说,你的Activity布局是FrameLayout,你定义了这个fitsSystemWindows,那么实际上也不会发生偏移,因为FrameLayout布局中没有对此进行适配

实际上的适配工作,就是布局判断下这个标识,然后自动的加上对应的偏移,就形成了上述我们要的效果

具体可以参考郭霖大佬的文章再学一遍android:fitsSystemWindows属性

fitsSystemWindows在ViewGroup中通过dispatchApplyWindowInsets()进行分发给子View

如果dispatchApplyWindowInsets 中把insets.consumeSystemWindowInsets()消费掉, 那么inset事件就无法传递到子View,子View设置fitsSystemWindows=true将会没有反应

View会通过onApplyWindowInsets()消费掉WindowInsets, 当然其要求是父View必须设置fitSystemWindows=false 这样WindowInsets才能传递到子View中进行消费

参考

Android 自动取色并设置沉浸式状态栏的更多相关文章

  1. 【mui webAPP】HBuilder创建的iOS平台设置沉浸式状态栏

    应用占用全屏区域,而系统状态栏需要预留出系统状态栏高度. HBuilder创建的应用默认不使用沉浸式状态栏样式,需要进行如下配置开启:打开应用的manifest.json文件,切换到代码视图,在plu ...

  2. 两句话,实现android 4.4以上实现沉浸式状态栏

    效果图如下,就是状态栏和actionbar保持一致的颜色,非常漂亮 1:在Activity的OnCreate函数 if (Build.VERSION.SDK_INT >= Build.VERSI ...

  3. vue项目 使用Hbuilder打包app 设置沉浸式状态栏

    使用 Hbuilder新建好移动app项目后,mainfest.json这个文件里的 plus里设置 statusbar ..... "plus": { "statusb ...

  4. HBuilder设置沉浸式状态栏显示效果

    1:在[manifest.json]文件中,在[plus-->distribute--> apple]下加上[ "UIReserveStatusbarOffset":f ...

  5. Android 4.4沉浸式状态栏的实现

    要实现Android 4.4上面的沉浸式状态栏要用到开源项目SystemBarTint(https://github.com/hexiaochun/SystemBarTint) public clas ...

  6. Android沉浸式状态栏(透明状态栏)最佳实现

    Android沉浸式状态栏(透明状态栏)最佳实现 在Android4.4之前,我们的应用没法改变手机的状态栏颜色,当我们打开应用时,会出现上图中左侧的画面,在屏幕的顶部有一条黑色的状态栏,和应用的风格 ...

  7. Android:沉浸式状态栏(一)工具类

    参考自Android 沉浸式状态栏完美解决方案 基本功能 状态栏深色或浅色图标切换 自定义状态栏背景 设置沉浸式状态栏 先准备几个工具类 1.SystemBarTintManager package ...

  8. CoordinatorLayout+沉浸式状态栏

    没有gif 说个*B 注意看 状态栏的瑶瑟变化 (如果我是你 我不会去计较下边的toast) 之前为了这个效果我查了好多文章 博客什么的   ,,要么就是刚开始图片背景没有填充到状态栏下   要么就是 ...

  9. android沉浸式状态栏设置(4.4以上版本)

    其实设置比较简单,我用了小米和htc的几款机型都可以用. 主要代码就是这个(注意要在Activity的setContentView之前调用才行) /** * 开启沉浸式状态栏 * */ public ...

随机推荐

  1. WinForms获得已打开窗体的引用

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月6日. 对于已经打开的窗口,可以通过Application.OpenForms属性进行获得.该属性是一个FormCollectio ...

  2. # 【由浅入深_打牢基础】WEB缓存投毒(上)

    image-20220611092344882 [由浅入深_打牢基础]WEB缓存投毒(上) 1. 什么是WEB缓存投毒 简单的来说,就是利用缓存将有害的HTTP响应提供给用户 什么是缓存,这里借用Bu ...

  3. UiPath官网认证中文教程

    RPA之家公众号:RPA之家 RPA之家官网:http://rpazj.com 斗鱼直播:http://www.douyu.com/rpazj UiPath中文社区QQ群:465630324 RPA& ...

  4. zabbix配置邮件报警

    1.yum源安装sendmail,sendmail-cf和mailx 2.关闭postfix,/etc/init.d/postfix stop chkconfig posfix off 3.启动sen ...

  5. RPA应用场景-财务报表统计整合

    场景概述 财务报表统计整合 所涉系统名称 邮储银行系统 人工操作(时间/次) 3小时 所涉人工数量 1 操作频率 每月 场景流程 1.登录各个区支行系统 2.机器人按照要求,自动复选多项业务参数,导出 ...

  6. window下Redis快速启动,以及闪退问题解决

    我下载的是免安装版的window版redis,解压后如下: 第一步:在解压的redis文件夹下新建一个redis-start.bat(window启动一般都是xx.bat) 第二步:打开redis.w ...

  7. ArrayList分析1-循环、扩容、版本

    ArrayList分析1-循环.扩容.版本 转载请注明出处 https://www.cnblogs.com/funnyzpc/p/16407733.html 前段时间抽空看了下ArrayList的源码 ...

  8. identityserver4 (ids4)中如何获取refresh_token刷新令牌token 使用offline_access作用域

    ids4默认自带的api接口/api/connect/token 调用这个接口的时候,需要在body里面的 x-www-form-urlencoded模式下写 {     grant_type: &q ...

  9. 【UR #2】猪猪侠再战括号序列 题解

    题目链接 前言 是的没脑子选手只会做签到题. 思路分析 一开始把题目看成反转括号的状态,直接浪费 \(40\ mins\) . 我们考虑把不确定的"正确括号"转换成一个固定的括号序 ...

  10. 异构图神经网络笔记-Heterogeneous Graph Neural Network(KDD19)

    自己讲论文做的异构图神经网络的ppt.再转变成博客有点麻烦,所以做成图片笔记. 论文链接:https://arxiv.org/abs/1903.07293