100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Android 自定义View颜色选择器( 条形 水平) 使用HSV颜色模型实现取色器并反向定

Android 自定义View颜色选择器( 条形 水平) 使用HSV颜色模型实现取色器并反向定

时间:2018-12-22 14:15:19

相关推荐

Android 自定义View颜色选择器( 条形 水平) 使用HSV颜色模型实现取色器并反向定

轻松实现一个简单的Android条形水平颜色选择器,可以通过设置颜色值反向定位滑块

Demo地址:/DonTiny/ColorPickDemo

效果图:

先贴完整代码:

/*** Author: Aeolou* Date:/3/14 0014* Email:tg0804013x@*/public class ColorBarView extends View {private static int[] colors;private OnColorChangeListener onColorChangeListener;private float width;private float height;//长条宽高private float barWidth;private float barHeight;//滑块private int thumbDrawable;private Bitmap thumbBitmap;//滑块宽高private float thumbWidth;private float thumbHeight;//滑块当前的位置private float currentThumbOffset;//彩色长条开始位置private float barStartX, barStartY;private static int STATUS;private static final int STATUS_INIT = 0;//移动了action barprivate static final int STATUS_SEEK = 1;//长条画笔private Paint barPaint;//滑块画笔private Paint thumbPaint;private int currentColor;public interface OnColorChangeListener {void onColorChange(int color);}public ColorBarView(Context context) {this(context, null);}public ColorBarView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public ColorBarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);initCustomAttrs(context, attrs);initView();}private void initView() {thumbBitmap = BitmapFactory.decodeResource(getResources(), thumbDrawable);}private void init(Context context) {//初始化渐变色initColors();STATUS = STATUS_INIT;barPaint = new Paint();barPaint.setAntiAlias(true);barPaint.setStrokeCap(Paint.Cap.ROUND);thumbPaint = new Paint();thumbPaint.setAntiAlias(true);thumbPaint.setStrokeCap(Paint.Cap.ROUND);}private void initColors() {int colorCount = 12;int colorAngleStep = 360 / colorCount;colors = new int[colorCount + 1];float[] hsv = new float[]{0f, 1f, 1f};for (int i = 0; i < colors.length; i++) {hsv[0] = 360 - (i * colorAngleStep) % 360;if (hsv[0] == 360) hsv[0] = 359;colors[i] = Color.HSVToColor(hsv);}}private void initCustomAttrs(Context context, AttributeSet attrs) {TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ColorBarView);if (typedArray != null) {thumbDrawable = typedArray.getResourceId(R.styleable.ColorBarView_thumbDrawable, R.mipmap.color_icon_button);barHeight = typedArray.getDimension(R.styleable.ColorBarView_barHeight, 30);thumbHeight = typedArray.getDimension(R.styleable.ColorBarView_thumbHeight, 80);typedArray.recycle();}}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));}/*** 测量高** @param heightMeasureSpec* @return*/private int measureHeight(int heightMeasureSpec) {int result = 0;int specMode = MeasureSpec.getMode(heightMeasureSpec);int specSize = MeasureSpec.getSize(heightMeasureSpec);if (specMode == MeasureSpec.EXACTLY) {//精确值模式result = Math.max(Math.max((int) thumbHeight, (int) barHeight), specSize);} else if (specMode == MeasureSpec.AT_MOST) {//最大值模式result = Math.max((int) thumbHeight, (int) barHeight + getPaddingTop() + getPaddingBottom());} else {result = specSize;}return result;}/*** 测量高** @param widthMeasureSpec* @return*/private int measureWidth(int widthMeasureSpec) {int result = 0;int specMode = MeasureSpec.getMode(widthMeasureSpec);int specSize = MeasureSpec.getSize(widthMeasureSpec);if (specMode == MeasureSpec.EXACTLY) {//精确值模式result = specSize;} else if (specMode == MeasureSpec.AT_MOST) {//最大值模式result = 200;}return result;}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {width = w;height = h;thumbWidth = thumbHeight * ((float) thumbBitmap.getWidth() / (float) thumbBitmap.getHeight());barWidth = width - thumbWidth;barStartX = thumbWidth / 2;//不从0开始,左右边缘用于显示滑块barStartY = height / 2 - barHeight / 2;super.onSizeChanged(w, h, oldw, oldh);}/*** 处理点击和滑动事件** @param event* @return*/@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {//点击时case MotionEvent.ACTION_DOWN:currentThumbOffset = (int) event.getX();if (currentThumbOffset <= thumbWidth / 2) currentThumbOffset = thumbWidth / 2 + 1;if (currentThumbOffset >= barWidth + thumbWidth / 2)currentThumbOffset = barWidth + thumbWidth / 2;STATUS = STATUS_SEEK;break;//滑动时case MotionEvent.ACTION_MOVE:currentThumbOffset = (int) event.getX();if (currentThumbOffset <= thumbWidth / 2) currentThumbOffset = thumbWidth / 2 + 1;if (currentThumbOffset >= barWidth + thumbWidth / 2)currentThumbOffset = barWidth + thumbWidth / 2;break;}changColor();if (onColorChangeListener != null) {onColorChangeListener.onColorChange(currentColor);}invalidate();return true;}@Overrideprotected void onDraw(Canvas canvas) {drawBar(canvas);drawThumb(canvas);super.onDraw(canvas);}/*** 滑动滑块使颜色发生变化*/private void changColor() {float position = currentThumbOffset - thumbWidth / 2.0f;//当前滑块中心的长度float colorH = 360 - position / barWidth * 360;currentColor = Color.HSVToColor(new float[]{colorH, 1.0f, 1.0f});}/*** 获取当前颜色** @return*/private int getCurrentColor() {return currentColor;}/*** 设置当前颜色** @param currentColor*/public void setCurrentColor(int currentColor) {this.currentColor = currentColor;if (onColorChangeListener != null) {onColorChangeListener.onColorChange(currentColor);}invalidate();}/*** 绘制底部颜色条** @param canvas*/private void drawBar(Canvas canvas) {barPaint.setShader(new LinearGradient(barStartX, barStartY + barHeight / 2,barStartX + barWidth, barStartY + barHeight / 2,colors, null, Shader.TileMode.CLAMP));canvas.drawRoundRect(new RectF(barStartX, barStartY, barStartX + barWidth,barStartY + barHeight), barHeight / 2, barHeight / 2, barPaint);}private void drawThumb(Canvas canvas) {float[] currentColorHSV = new float[3];Color.RGBToHSV(Color.red(currentColor), Color.green(currentColor), Color.blue(currentColor), currentColorHSV);//根据HSV计算颜色所在位置float position = barWidth * currentColorHSV[0] / 360.0f;currentThumbOffset = barWidth - position + thumbWidth / 2;canvas.drawBitmap(thumbBitmap, null, getThumbRect(), thumbPaint);}/*** 获取滑块所在的矩形区域*/private RectF getThumbRect() {return new RectF(currentThumbOffset - thumbWidth / 2, height / 2 - thumbHeight / 2,currentThumbOffset + thumbWidth / 2, height / 2 + thumbHeight / 2);}public void setOnColorChangerListener(OnColorChangeListener onColorChangerListener) {this.onColorChangeListener = onColorChangerListener;}}

关键代码及实现方式:

首先使用HSV模型(有兴趣可以百度了解)绘制渐变。先通过HSV计算出一个渐变色数组后,这里由于H值为1和360时颜色值完全一致,则将其置为359,避免首尾颜色完全一致(其实也还是红色),这然后使用LinearGradient绘制渐变颜色条。不想首尾都是红色可以在此自行修改渐变数组,比如去掉第一个或最后一个颜色

//初始化渐变色private void initColors() {int colorCount = 12;int colorAngleStep = 360 / colorCount;colors = new int[colorCount + 1];float[] hsv = new float[]{0f, 1f, 1f};for (int i = 0; i < colors.length; i++) {hsv[0] = 360 - (i * colorAngleStep) % 360;if (hsv[0] == 360) hsv[0] = 359;colors[i] = Color.HSVToColor(hsv);}}

/*** 绘制底部颜色条** @param canvas*/private void drawBar(Canvas canvas) {barPaint.setShader(new LinearGradient(barStartX, barStartY + barHeight / 2,barStartX + barWidth, barStartY + barHeight / 2,colors, null, Shader.TileMode.CLAMP));canvas.drawRoundRect(new RectF(barStartX, barStartY, barStartX + barWidth, barStartY + barHeight), barHeight / 2, barHeight / 2, barPaint);}

当滑块滑动时只需计算当前滑块位置与彩色长条的比值即可计算出当前位置所对应的颜色的H值, 因为在这里使用HSV颜色模型时只需使用到H(色调0-360),而无需在意S(饱和度)、V(明度)。所以只需根据当前滑块所在色条中的位置即可计算出当前颜色的H值,得到当前颜色的HSV数组,再将其转换为int 颜色值。

/*** 滑动滑块使颜色发生变化*/private void changColor() {float position = currentThumbOffset - thumbWidth / 2.0f;//当前滑块中心的长度float colorH = 360 - position / barWidth * 360;currentColor = Color.HSVToColor(new float[]{colorH, 1.0f, 1.0f});}

同理,当需要设置颜色刷新定位滑块位置时,可先将int 类型Color转换为HSV颜色数组以得到其H值,再根据其与最大色调值360的比值计算出当前滑块应在色条中的位置,即可完成反向颜色定位。关键代码就这点,只要了解一下HSV颜色模型就很好理解。

/*** 设置当前颜色** @param currentColor*/public void setCurrentColor(int currentColor) {this.currentColor = currentColor;if (onColorChangeListener != null) {onColorChangeListener.onColorChange(currentColor);}invalidate();}/*** 绘制滑块* @param canvas*/private void drawThumb(Canvas canvas) {float[] currentColorHSV = new float[3];Color.RGBToHSV(Color.red(currentColor), Color.green(currentColor), Color.blue(currentColor), currentColorHSV);//根据HSV计算颜色所在位置float position = barWidth * currentColorHSV[0] / 360.0f;currentThumbOffset = barWidth - position + thumbWidth / 2;canvas.drawBitmap(thumbBitmap, null, getThumbRect(), thumbPaint);}

Android 自定义View颜色选择器( 条形 水平) 使用HSV颜色模型实现取色器并反向定位颜色所在位置

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。