其他
给你的Android应用穿件花衣服吧!
https://www.jianshu.com/u/11d3f06afbcd
说到拾色器,大家可能就会想到Photoshop, 使用得最多的应该是设计, 对于开发而言,平常要用到拾色器的机会不多。
如果有一天,项目中需要一个拾色器(多用于自定义颜色),该如何入手?今天且来给大家分享一下拾色器的设计和实现。
颜色空间也称彩色模型(又称彩色空间或彩色系统),它的用途是在某些标准下用通常可接受的方式对彩色加以说明。本节主要摘录各大神的一些表述,并加以整理。
RGB空间
红、绿、蓝三个颜色通道每种色各分为256阶亮度,在0时“灯”最弱——是关掉的,而在255时“灯”最亮。
当三色灰度数值相同时,产生不同灰度值的灰色调,即三色灰度都为0时,是最暗的黑色调;三色灰度都为255时,是最亮的白色调。
HSB空间
H(Hue) 为色相, 取值范围:0-360°,基础颜色。 S(Saturation) 为饱和度, 取值范围:0 - 1(0% - 100%), 表示色彩的纯度。 B(Brightness)为明度, 取值范围:0 - 1(0% - 100%),表示对光量的感知。
明度在某些地方也叫Value,所以就有了HSV,HSV和HSB是一样的,只是关于明度的叫法不一样而已。
色相环的每一种颜色,在RGB空间中,最多只有两个颜色通道(r, g, b)大于0,所以色相环的颜色是最纯净的。 明度决定了RBG三个分量的大小,也就是决定了光亮的大小,在感知层面,就是明暗的区别。 饱和度为0的颜色,r,g,b相等, 当明度为0时为黑色,明度为1时为白色,大于0小于1时为灰色; 饱和度为1时,颜色值仅取决于色相和明度,而明度只控制RGB分量的大小,所以颜色还是纯净的; 饱和度在0到1之间时,为饱和度为0的颜色(黑灰白)和饱和度为1的颜色的线性插值,越靠近1颜色越纯净。
明度
饱和度
色相
HSB转RGB
当i=0(第一段),(r, g, b) = (v, t, p) = (1, f, 0), 而f=h/60-hi =h/60,
也就是,第一段中,r=1, g=h/60, b=0;特例:当h=60, r=1,g=1,b=0, 混合出黄色。以此类推。另外我们还注意到,当h选定之后,颜色和s,v成线性关系,这一点对后面拾色器的实现很重要。
条形拾色器
可能网易的设计师只想让用户选取鲜明的颜色,所以舍弃了饱和度的调节,同时换来了极大的简洁性。
环形拾色器
https://github.com/LarsWerkman/HoloColorPicker
PS拾色器
幸运的是,SDK 的 Color 类提供HSB(HSV)和RGB之间的转换方法:
public static int HSVToColor(@Size(3) float hsv[])
同样,SDK也提供了各种Shader, 使得我们可以轻松的绘制各种坐标。接下来我们结合实例看一下。
仿网易云音乐
前面我们提到,色相是分段线性变化的,因此,我们可以利用 LinearGradient 来绘制。
@Nullable float positions[], @NonNull TileMode tile)
0xFFFF0000,
0xFFFFFF00,
0xFF00FF00,
0xFF00FFFF,
0xFF0000FF,
0xFFFF00FF,
0xFFFF0000,
};
colors[0] = Color.HSVToColor(hsv);
hsv[1] = 1f;
colors[1] = Color.HSVToColor(hsv);
仿Photoshop
@NonNull @ColorInt int colors[], @Nullable float positions[])
if (mValShader == null) {
mValShader = new LinearGradient(
mSVRect.left, mSVRect.top,
mSVRect.left, mSVRect.bottom,
Color.WHITE, Color.BLACK, Shader.TileMode.CLAMP);
}
if (mShaderHSV[0] != mHSV[0] || mComposeShader == null) {
mShaderHSV[0] = mHSV[0];
Shader satShader = new LinearGradient(
mSVRect.left, mSVRect.top,
mSVRect.right, mSVRect.top,
Color.WHITE, Color.HSVToColor(mShaderHSV), Shader.TileMode.CLAMP);
mComposeShader = new ComposeShader(mValShader, satShader, PorterDuff.Mode.MULTIPLY);
}
return mComposeShader;
}
如果要实时预览效果,那拾色器就不能占太多空间,这时候第一种方案会比较适合;如果要制作调色板之类的,用第二种方案就比较高效。
https://github.com/No89757/ColorPicker