自定义View:Android(安卓)仿 PS 选色板
前言
今天突然发现年前的文章竟然没有写完,略微有点尴尬。今天分享的主题是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地址
更多相关文章
- Android绘图机制与处理技巧(二)——Android图像处理之色彩特效处理
- 【移动开发】Android中不用图片资源也能做出好看的界面
- 2013.12.05(6)——— android ViewPagerIndicator之SampleTitlesDe
- Android(安卓)UI 常用颜色
- android布局layout边框颜色
- LinearLayout设置灰色边框,只保留底部边框,去掉三个框的技巧。
- Android(安卓)QQ通知小红点
- 2013.12.05(4)——— android ViewPagerIndicator之SampleLinesDef
- 改变滚动条的颜色ScrollView