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)
            }
  1. 然后根据获取的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;

        @Override
        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)



参考链接
1.[使用 Palette API 选择颜色](https://developer.android.google.cn/training/material/palette-colors)
2.[使用 Palette 让你的 UI 色彩与内容更贴合](https://segmentfault.com/a/1190000011069612)

你可能感兴趣的:(Android,android)