网络编程

当前位置:永利402游戏网站-永利402com官方网站 > 网络编程 > 【Android自定义View】仿Photoshop取色器ColorPicker(二

【Android自定义View】仿Photoshop取色器ColorPicker(二

来源:http://www.xtcsyb.com 作者:永利402游戏网站-永利402com官方网站 时间:2019-10-01 21:35

一款仿Photoshop取色器的Android版取色器。

一款仿Photoshop取色器的Android版取色器。

github地址:

github地址:

上一篇已经简介了ColorPicker的系列结构以及三种颜色空间,接下去我们详细解析一下ColorPicker的主干自定义控件ColorPickerView。

上一篇已经简要介绍了ColorPicker的着力自定义控件ColorPickerView的绘图流程。接下来咱们详细分析一下ColorPickerView的监听事件相关代码。

在读书代码在此之前,大家先看一下ColorPicker的布局以及一些标号的数值在代码里的变量名称。

注:

图片 1介绍图片 2变量名

  • 1 倘使您对HSV颜色空间和本田CR-VGB颜色空间远远不够纯熟的话,请仿效该类别的第一篇小说【Android自定义View】仿Photoshop取色器ColorPicker
  • 2 假令你对ColorPickerView的绘图流程面生的话 ,请参照他事他说加以考察该连串的第二篇文章【Android自定义View】仿Photoshop取色器ColorPicker

变量名标明的的大图

在讲颜色退换监听此前,先来说讲初始颜色传入时,代码的改换呢!

读书三个自定义View的代码,只需记住四步走:构造方法onMeasureonLayoutonDraw

  • 1 先把奔驰M级GB颜色转化成HSV三个值
  • 2 刷新页面invalidate

构造方法

public ColorPickerView(Context context) { this(context, null);}public ColorPickerView(Context context, AttributeSet attrs) { this(context, attrs, 0);}public ColorPickerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init();}

可知,前2个构造器最终都调用了第三个构造器。而第多个布局器里的首要内容都在二个名称叫init()的方法。

private void init() { mDensity = getContext().getResources().getDisplayMetrics().density;//获取屏幕密度 mSVTrackerRadius *= mDensity;//灰度饱和度指示器的半径 mRectOffset *= mDensity;//H、SV矩形与父布局的边距 mHuePanelWidth *= mDensity;//H矩形的宽度 mPanelSpacing *= mDensity;//H、SV矩形间的间距 mPreferredHeight *= mDensity;//当mode为MeasureSpec.UNSPECIFIED时的首选高度 mPreferredWidth *= mDensity;//当mode为MeasureSpec.UNSPECIFIED时的首选宽度 mDrawingOffset = calculateRequiredOffset();//计算所需位移 initPaintTools();//初始化画笔、画布 setFocusable;//设置可获取焦点 setFocusableInTouchMode;//设置在被触摸时会获取焦点}

init格局里有好多变量,它们的意义如下图所示:

图片 3变量名

说明:调用invalidate后,View会触发onDraw()措施,由此七个调色板会根据今日的HSV值绘制当前来得的色板以及提示器的地点。

onMeasure

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthAllowed = MeasureSpec.getSize(widthMeasureSpec); int heightAllowed = MeasureSpec.getSize(heightMeasureSpec); widthAllowed = isUnspecified(widthMode) ?  mPreferredWidth : widthAllowed; heightAllowed = isUnspecified(heightMode) ?  mPreferredHeight : heightAllowed; int width = widthAllowed; int height =  (widthAllowed - mPanelSpacing - mHuePanelWidth); //当根据宽度计算出来的高度大于可允许的最大高度时 或 当前是横屏 if (height > heightAllowed || "landscape".equals) { height = heightAllowed; width =  (height + mPanelSpacing + mHuePanelWidth); } setMeasuredDimension(width, height);}private static boolean isUnspecified { return !(mode == MeasureSpec.EXACTLY || mode == MeasureSpec.AT_MOST);}

衡量方式(MeasureSpecMode)分为EXACTLYAT_MOSTUNSPECIFIED二种档案的次序。前二种档案的次序能够透过MeasureSpec.getSize(int measureSpec)获得实际的值;当度量方式为UNSPECIFIED时,须求我们风雨同舟明显自定义View的高宽。这里作者设定了一部分暗中认可值,使ColorPicker看起来更安适。

public void setColor(int color) { setColor(color, false);}public void setColor(int color, boolean callback) { float[] hsv = new float[3]; Color.colorToHSV(color, hsv); mHue = hsv[0]; mSat = hsv[1]; mVal = hsv[2]; if (callback && mListener != null) { mListener.onColorChanged(Color.HSVToColor(new float[]{mHue, mSat, mVal})); } invalidate();}

onLayout

那边运用了父类的onLayout方法。

在增选颜色进度中,会接触二种监听事件:轨迹球拖拽事件(onTrackballEvent)、显示屏点击事件(onTouchEvent)

onDraw

绘制ColorPickerView分为八个部分:饱和度灰度调色板mSatValRect+色相调色板mHueRect

@Overrideprotected void onDraw(Canvas canvas) { if (mDrawingRect.width() <= 0 || mDrawingRect.height() <= 0) return; drawSatValPanel;//绘制SV选择区域 drawHuePanel;//绘制右侧H选择区域}

起先询问实际绘制细节在此之前,希望读者已经领悟过Shader的有关文化。

1 先画二个大矩形,再在地方画我们的饱和度灰度调色板,那样看起来有八个描边的作用。2 绘制饱和度灰度提示器。依照当下增选的水彩定位到实际的坐标,在这几个坐标上做画。先画一个半径为mSVTrackerRadius、边线粗细为mDensity的空心大圆,再在上边画叁个半径为mSVTrackerRadius-mDensity、边线粗细为mDensity的空心小圆。

/** * 绘制S、V选择区域 * * @param canvas 画布 */private void drawSatValPanel(Canvas canvas) { //描边(先画一个大矩形, 再在内部画一个小矩形,就可以显示出描边的效果) mBorderPaint.setColor(mBorderColor); canvas.drawRect( mDrawingRect.left, mDrawingRect.top, mSatValRect.right + BORDER_WIDTH, mSatValRect.bottom + BORDER_WIDTH, mBorderPaint); //组合着色器 = 明度线性着色器 + 饱和度线性着色器 ComposeShader mShader = generateSVShader(); mSatValPaint.setShader; canvas.drawRect(mSatValRect, mSatValPaint); //初始化选择器的位置 Point p = satValToPoint(mSat, mVal); //绘制显示SV值的选择器 mSatValTrackerPaint.setColor(0xff000000); canvas.drawCircle(p.x, p.y, mSVTrackerRadius - 1f * mDensity, mSatValTrackerPaint); //绘制外圆 mSatValTrackerPaint.setColor(0xffdddddd); canvas.drawCircle(p.x, p.y, mSVTrackerRadius, mSatValTrackerPaint);}/** * 创建SV着色器(明度线性着色器 + 饱和度线性着色器) * * @return 着色器 */private ComposeShader generateSVShader() { //明度线性着色器 if (mValShader == null) { mValShader = new LinearGradient(mSatValRect.left, mSatValRect.top, mSatValRect.left, mSatValRect.bottom, 0xffffffff, 0xff000000, TileMode.CLAMP); } //HSV转化为RGB int rgb = Color.HSVToColor(new float[]{mHue, 1f, 1f}); //饱和线性着色器 Shader satShader = new LinearGradient(mSatValRect.left, mSatValRect.top, mSatValRect.right, mSatValRect.top, 0xffffffff, rgb, TileMode.CLAMP); //组合着色器 = 明度线性着色器 + 饱和度线性着色器 return new ComposeShader(mValShader, satShader, PorterDuff.Mode.MULTIPLY);}

1 同理绘制矩形调色板2 同理绘制空心圆角矩形

/** * 绘制右侧H选择区域 * * @param canvas 画布 */private void drawHuePanel(Canvas canvas) { final RectF rect = mHueRect; mBorderPaint.setColor(mBorderColor); canvas.drawRect(rect.left - BORDER_WIDTH, rect.top - BORDER_WIDTH, rect.right + BORDER_WIDTH, rect.bottom + BORDER_WIDTH, mBorderPaint); //初始化H线性着色器 if (mHueShader == null) { int[] hue = new int[361]; int count = 0; for (int i = hue.length - 1; i >= 0; i--, count++) { hue[count] = Color.HSVToColor(new float[]{i, 1f, 1f}); } mHueShader = new LinearGradient( rect.left, rect.top, rect.left, rect.bottom, hue, null, TileMode.CLAMP); mHuePaint.setShader(mHueShader); } canvas.drawRect(rect, mHuePaint); float halfHTrackerHeight= mHTrackerHeight / 2; //初始化H选择器选择条位置 Point p = hueToPoint; RectF r = new RectF(); r.left = rect.left - mRectOffset; r.right = rect.right + mRectOffset; r.top = p.y - halfHTrackerHeight; r.bottom = p.y + halfHTrackerHeight; //绘制选择条 canvas.drawRoundRect(r, 2, 2, mHueTrackerPaint);}

那样一来,整个ColorPickerView的绘图流程就都在这边了。下一篇首要教学ColorPickerView的最先化颜色传入和颜色更改监听回调:【Android自定义View】仿Photoshop取色器ColorPicker

轨道球拖拽事件onTrackball伊芙nt

入眼那边的代码,这里分为三种情状处理:

  • 现阶段触点在[饱和度灰度调色板]上
    • 遵照x、y坐标获得sat、val值
  • 当下触点在[色相调色板]上
    • 传闻y轴坐标拿到hue值

谈起底再将HSV值换算成XC90GB值,通过监听器回调给上一级(ColorPickerDialog)

@Overridepublic boolean onTrackballEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); boolean isUpdated = false; if (event.getAction() == MotionEvent.ACTION_MOVE) { switch (mLastTouchedPanel) { case PANEL.SAT_VAL: float sat, val; sat = mSat + x / 50f; val = mVal - y / 50f; if (sat < 0f) { sat = 0f; } else if (sat > 1f) { sat = 1f; } if (val < 0f) { val = 0f; } else if (val > 1f) { val = 1f; } mSat = sat; mVal = val; isUpdated = true; break; case PANEL.HUE: float hue = mHue - y * 10f; if (hue < 0f) { hue = 0f; } else if (hue > 360f) { hue = 360f; } mHue = hue; isUpdated = true; break; } } if (isUpdated) { if (mListener != null) { mListener.onColorChanged(Color.HSVToColor(new float[]{mHue, mSat, mVal})); } invalidate(); return true; } return super.onTrackballEvent;}

显示屏点击事件onTrackball伊夫nt

  • 1 监听了手指的DOWN、UP、MOVE的平地风波
  • 2 具体管理逻辑在moveTrackersIfNeeded()方法中
    • 2.1 先推断触点是不是在调色板内
    • 2.2 然后基于调色板更新对应的sat、val值或hue值
  • 3 遵照是不是更新了颜色进行监听回调
  • 4 刷新页面invalidate();
@Overridepublic boolean onTouchEvent(MotionEvent event) { boolean isUpdated = false; switch (event.getAction { case MotionEvent.ACTION_DOWN: mStartTouchPoint = new Point event.getX event.getY; isUpdated = moveTrackersIfNeeded; break; case MotionEvent.ACTION_MOVE: isUpdated = moveTrackersIfNeeded; break; case MotionEvent.ACTION_UP: mStartTouchPoint = null; isUpdated = moveTrackersIfNeeded; break; } if (isUpdated) { if (mListener != null) { mListener.onColorChanged(Color.HSVToColor(new float[]{mHue, mSat, mVal})); } invalidate(); return true; } return super.onTouchEvent;}private boolean moveTrackersIfNeeded(MotionEvent event) { if (mStartTouchPoint == null) return false; boolean update = false; int startX = mStartTouchPoint.x; int startY = mStartTouchPoint.y; if (mHueRect.contains(startX, startY)) { mLastTouchedPanel = PANEL.HUE; mHue = pointToHue(event.getY; update = true; } else if (mSatValRect.contains(startX, startY)) { mLastTouchedPanel = PANEL.SAT_VAL; float[] result = pointToSatVal(event.getX(), event.getY; mSat = result[0]; mVal = result[1]; update = true; } return update;}

末段汇总一下,明天那篇文章主要讲了,ColorPickerView的开头颜色传入+颜色改造监听。下一篇将执教ColorPickerDialog的首要性代码,敬请期望。

本文由永利402游戏网站-永利402com官方网站发布于网络编程,转载请注明出处:【Android自定义View】仿Photoshop取色器ColorPicker(二

关键词:

上一篇:心怀

下一篇:没有了