前言

我们知道,Android系统为我们提供了一个计算颜色的Evaluator—ArgbEvaluator,为什么还要去实现一个HsvEvaluator。这当然是有其道理的,HSV的变换更符合人眼的直觉,可以看看下面HSV的详细解析。
先看看HSV颜色格式
HSV颜色空间中不同颜色对应的灰度范围
在机器视觉领域,我们除了对物体的外形,纹理特征进行检测识别,也可以利用颜色来识别不同物体。
比如水果的成熟程度。HSV指的是Hue色调分量,Saturation饱和度,Intensity明亮度。
以下摘自百度百科:
色调H
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
饱和度S
饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
亮度V(I:明度)
明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
在HSV颜色空间中颜色分量Hue对应不同颜色的灰度范围如下:

  • 0<=h<20, 红色
  • 30<=h<45, 黄色
  • 45<=h<90, 绿色
  • 90<=h<125, 青色
  • 125<=h<150, 蓝色
  • 150<=h<175, 紫色
  • 175<=h<200, 粉红色
  • 200<=h<220, 砖红色
  • 220<=h<255, 品红色
    image.png

自定义Evaluator

实现Evaluator需要继承TypeEvaluator并重写evaluate()
在下面的代码中,HsvEvaluator继承TypeEvaluator并重写evaluate()evaluate()中的代码虽然多,但是并不复杂,核心是先将ARGB格式的颜色转换为HSV格式的颜色,并根据公式$out = begin + (end - begin) * fractionout=begin+(end−begin)∗fraction$来计算出当前动画对应的值,最后将HSV格式的颜色转换会ARGB格式,返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class HsvEvaluator() : TypeEvaluator<Int> {
val startHsv = FloatArray(3)
val endHsv = FloatArray(3)
val outHsv = FloatArray(3)
override fun evaluate(fraction: Float, startValue: Int?, endValue: Int?): Int {
//转换ARGB为HSV
//计算当前动画所对应的透明度
val outAlpha = if (startValue != null && endValue != null){
Color.colorToHSV(startValue, startHsv)
Color.colorToHSV(endValue, endHsv)
startValue shr 24 + ((endValue shr 24 - startValue shr 24) * fraction).toInt()
}else{
0
}

//计算动画完成度
if (endHsv[0] - startHsv[0] > 180f) {
endHsv[0] -= 360f
} else if (endHsv[0] - startHsv[0] < -180f) {
endHsv[0] += 360f
}
outHsv[0] = startHsv[0] + (endHsv[0] - startHsv[0]) * fraction
outHsv[0] = (outHsv[0] + 360f) % 360
outHsv[1] = startHsv[1] + (endHsv[1] - startHsv[1]) * fraction
outHsv[2] = startHsv[2] + (endHsv[2] - startHsv[2]) * fraction

//将HSV转换为ARGB
return Color.HSVToColor(outAlpha,outHsv)
}
}

看看效果

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
val animatorSet = AnimatorSet().apply {
playTogether(
ObjectAnimator.ofInt(
findViewById(R.id.textView),"backgroundColor",
Color.RED,Color.GREEN
).apply {
setEvaluator(ArgbEvaluator())
},
ObjectAnimator.ofInt(
findViewById(R.id.textView1),"backgroundColor",
Color.RED,Color.GREEN
).apply {
setEvaluator(HsvEvaluator())
}
)
}
animatorSet.setDuration(5000).start()

HSV.gif
无论是HsvEvalutator,还是ArgbEvaluator都能完成颜色的平滑过度,但是仔细观察,就会觉得HsvEvalutator处理的颜色看得更顺眼一些,而ArgbEvaluator完成的颜色过度,会在一些时候显得更暗。这是自然的,HSV是为人类设计的颜色格式,而ARGB是为机器设计的格式。
总结
因此,在以后用到颜色的过度动画,我更推荐使用HsvEvalutator去计算颜色动画完成度。