android自定义颜色选择器,自定义View:Android 仿 PS 选色板

本文详细介绍了如何在Android中实现一个仿Photoshop的HSV颜色选择器。通过使用HSV颜色模型,结合系统提供的API进行RGB与HSV之间的转换,实现了色相、饱和度和明度的调节功能。文章还提供了具体的代码示例,包括绘制色相选择条和渐变色块的方法,以及根据触摸位置获取颜色的逻辑。最后,给出了完整的Demo链接供读者参考学习。
摘要由CSDN通过智能技术生成

前言

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

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

dfb8a807b180

效果图

正文

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

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

dfb8a807b180

在这里插入图片描述

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

// RGB转HSV

val hsv = FloatArray(3)

Color.HSVToColor(hsv)

hsv[0] // 色相

hsv[1] // 饱和度

hsv[2] // 明度

// HSV转RGB

val color = Color.HSVToColor(hsv)

// HSV转ARGB

val 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] = 0f

val startColor = Color.HSVToColor(hsv)

// 再保存饱和度为1的颜色

hsv[1] = 1f

val 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地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值