Palette咋取不了黑白色?
1.来个需求
最近有个需求,根据用户设置的个人主页背景改变字体颜色,想想这个比根据手机壳改变主题的需求相比还算合理。那就想想怎么做吧。
我想Android 中有个Palette库(implementation 'androidx.palette:palette:1.0.0')应该可以做。
我的思路大致如下
1 .利用Palette 获取图片的主色调
Palette.from(bitmap) .generate { palette -> if (palette != null) { val dominantColor = palette.getDominantColor(Color.BLACK) }
- 然后根据获取的dominantColor 的亮度来设置文字颜色。
val textColor= if(ColorUtils.calculateLuminance(dominantColor)>=0.5) { //图片主色调是是亮色 则文字颜色就是黑色 Color.BLACK }else{ Color.WHITE }
还有一种方案是利用Palette 提供的api 设置文字颜色,但我感觉效果不是很好
val textColor=palette.dominantSwatch?.bodyTextColor?:Color.BLACK
目前我就想到这两种方案,如果大家有比较好的方案,可以在评论区说一说,欢迎大家提供解决方案。
2.遇到个问题,K.O它
在项目中我使用的方案一,测试了几张图片感觉还可以。但是当我测试用比较纯白或者纯黑的图片测试的时候,发现 palette.getDominantColor(Color.BLACK) 取到的都是默认值,无法获取图片的主要颜色。
先说说解决方法,就是使用clearFilters() 方法
Palette.from(bitmap) //清除默认的颜色过滤器 .clearFilters() .generate { palette -> if (palette != null) { val dominantColor = palette.getDominantColor(Color.GRAY) } }
下面在说说为啥,那就不得不去看看Palette内部干了些啥事。
filter 的功能是过滤一些颜色,在Palette 构造方法中添加了一个默认过滤器,这个默认过滤器代码实现如下
static final Filter DEFAULT_FILTER = new Filter() { private static final float BLACK_MAX_LIGHTNESS = 0.05f; private static final float WHITE_MIN_LIGHTNESS = 0.95f; public boolean isAllowed(int rgb, float[] hsl) { return !isWhite(hsl) && !isBlack(hsl) && !isNearRedILine(hsl); } /** * @return true if the color represents a color which is close to black. */ private boolean isBlack(float[] hslColor) { return hslColor[2] <= BLACK_MAX_LIGHTNESS; } /** * @return true if the color represents a color which is close to white. */ private boolean isWhite(float[] hslColor) { return hslColor[2] >= WHITE_MIN_LIGHTNESS; } /** * @return true if the color lies close to the red side of the I line. */ private boolean isNearRedILine(float[] hslColor) { return hslColor[0] >= 10f && hslColor[0] <= 37f && hslColor[1] <= 0.82f; } };
Filter 是了接口 它又一个isAllowed 方法,决定允许获取的颜色。在上面DEFAULT_FILTER 中 的方法定义是不是黑色 且不是白色 还有不是isNearRedILine (??什么颜色)才可以 通过。所以默认过滤器过滤了黑色和白色,所以导致上面那种问题。
上面是通过方法中是hsl模式(HSL)来表达颜色的。在Android中是通过一个数组长度为3的float 数组表示的
数组下标0 对应的值表示 色相(Hue ) 取值为[0,360]、数组下标1 对应的值表示 饱和度 Saturation 取值范围为[0,1]、数组下标2对应的值表示 亮度 Lightness 取值范围为[0,1]。在Android 的ColorUtils 类中提供了rgb模式下的color转hsl模式的方法 colorToHSL(@ColorInt int color, @NonNull float[] outHsl)
参考链接