前言

今天突然发现年前的文章竟然没有写完,略微有点尴尬。今天分享的主题是Android仿PS选色板。

记得我刚开始学习Android的时候,就一直对PS选色板有一种执着,终于在今年找到了理想的解决方案。首先动图镇楼:

正文

我们常用的颜色主要是为ARGB还有RGB,不过这种组合格式想要实现选色板确实有点力不从心。从图上看,我们需要的二维矩阵,横向是饱和度的变化,纵向是明亮度的变化,类似我们电视机的色彩调节模式。ARGB和RGB是基本色的互相填充,想要精确把控颜色的变化还是很难的。

终于某一天我在网上偶然看到了新的颜色组合格式:HSV。


上面的简单介绍了HSV颜色的构成,非常符合选色板的要求,而且Android有系统API帮助我们把颜色在RGB和HSV之间互相转换。

// RGB转HSVval hsv = FloatArray(3)Color.HSVToColor(hsv)hsv[0] // 色相hsv[1] // 饱和度hsv[2] // 明度// HSV转RGBval color = Color.HSVToColor(hsv)// HSV转ARGBval color = Color.HSVToColor(alpha, hsv)

绘制右侧的色相选择条

首先我们绘制右侧的色相选择条,把需要的色相按照均等渐变绘制一下:

private fun initLinearGradient() {        positions = FloatArray(colorArray.size)        for (i in colorArray.indices) {            positions[i] = i * (1f / (colorArray.size - 1))        }        shader = LinearGradient(            0f, 0f, measuredWidth.toFloat(), measuredHeight.toFloat(),            colorArray, positions, Shader.TileMode.CLAMP        )}

然后根据onTouchEvent的位置,计算手指按压的位置,到底是什么颜色,我这采取的方案是ArgbEvaluator:

 /**     * 计算应该当前的颜色值     * */    private fun calculateCurrentColor(): Int {        // 找到两个颜色区间        if (progress == 0f) {            return colorArray.first()        }        if (progress >= 1f) {            return colorArray.last()        }        var startColor = 0        var endColor = 0        var ratio = 0f        var i = positions.size - 1        while (i >= 0) {            if (progress >= positions[i]) {                startColor = colorArray[i]                endColor = colorArray[i + 1]                ratio = (progress - positions[i]) / (positions[i + 1] - positions[i])                break            }            i--        }        val argbEvaluator = ArgbEvaluator()        return argbEvaluator.evaluate(ratio, startColor, endColor) as Int    }

ArgbEvaluator只能计算两个颜色,所以我需要知道手指按压的位置处于哪两个颜色之间,刚才我们绘制渐变色的时候:

positions = FloatArray(colorArray.size)

已经记录了每一个颜色的位置,和手指的y坐标和View高度的比例是对应的,这样就可以具体颜色,不过颜色的格式RGB。

绘制左侧的渐变自定义View

从右侧的色相选择条得到了色相,第一步,把RGB转换为HSV,下面以横向饱和度为例:

Color.colorToHSV(it, hsv)// 记录色相的饱和度val temp = hsv[1]// 保存饱和度为0的颜色hsv[1] = 0fval startColor = Color.HSVToColor(hsv)// 再保存饱和度为1的颜色hsv[1] = 1fval endColor = Color.HSVToColor(hsv)// 恢复之前的颜色hsv[1] = temp// 画出饱和度从0到1的渐变色return LinearGradient(          0f, 0f, width.toFloat(), 0f,          intArrayOf(startColor, endColor),          floatArrayOf(0f, 1f),          Shader.TileMode.CLAMP)

同理可以得到明度从0到1的渐变,然后两种渐变叠加在一起,我们的二维选择器就完成了。

HSV转RGB

接下来的问题是如何返回手指按下的颜色,这个和之前计算色相选择的道理一样,饱和度和明度的范围都是从0到1的,所以我们根据手指的x坐标和y坐标,求出坐标和宽高的比例,就是对应的饱和度的明度:

// 替换颜色饱和度和明度,返回RGB的颜色private fun calculateCurrentColor(xDown: Float, yDown: Float): Int {    val saturation = xDown / width    val brightness = yDown / height    hsv[1] = saturation    hsv[2] = 1- brightness    return Color.HSVToColor(hsv)}

总结

其实选择器的核心思想就是RGB颜色和HSV颜色的互相转换,其他的都是逻辑问题。
具体demo请点击:选色板demo Github地址

更多相关文章

  1. Android绘图机制与处理技巧(二)——Android图像处理之色彩特效处理
  2. 【移动开发】Android中不用图片资源也能做出好看的界面
  3. 2013.12.05(6)——— android ViewPagerIndicator之SampleTitlesDe
  4. Android(安卓)UI 常用颜色
  5. android布局layout边框颜色
  6. LinearLayout设置灰色边框,只保留底部边框,去掉三个框的技巧。
  7. Android(安卓)QQ通知小红点
  8. 2013.12.05(4)——— android ViewPagerIndicator之SampleLinesDef
  9. 改变滚动条的颜色ScrollView

随机推荐

  1. Android中LocalSocket使用
  2. Android第一个应用程序helloworld项目详
  3. Android(安卓)Studio 编译系统源码
  4. logcat使用方法
  5. android6.0以后删除HttpClient的解决方法
  6. Custom View
  7. ViewPager实现引导页
  8. 安卓设备修改屏幕像素密度以及查看屏幕分
  9. 【odroid-xu3】 ODROID-XU3软件环境搭建
  10. Android常用组件整理