Android应用开发--颜色拾取器,color picker

时间:2022-07-12 17:11:53

做一个项目,需要用到颜色拾取器,最后效果如下:

Android应用开发--颜色拾取器,color picker


二:代码如下

public class ColorPickerView extends View {
	private Paint mPaint;// 渐变色环画笔
	private Paint mClickPaint;// 触控点画笔
	private int clickX = 0;
	private int clickY = 0;
	public OnColorChangedListener mListener;
	private ImageView smallCircle;  //中间的小圆,手指触控滑动
        //颜色数组,用这个值来画圆的颜色
	private final int[] mCircleColors = new int[] { 0xFFFF0000, 0xFFFF00FF,
			0xFF0000FF, 0xFF00FFFF, 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000 };
        //色圆的尺寸
	private int mHeight;// View高
	private int mWidth;// View宽
        //可以画成色环
	private float r;// 色环半径(paint中部)

	private boolean downInCircle = true;// 按在渐变环上


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

	private void init(Context context) {
		mHeight = 660;
		mWidth = 660;
		setFocusable(true);
		setFocusableInTouchMode(true);

                //准备色圆的画笔
		Shader s = new SweepGradient(0, 0, mCircleColors, null);
		mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); // 抗锯齿
		mPaint.setShader(s);
		mPaint.setStyle(Paint.Style.FILL); // 设置实心

		r = mWidth / 2 * 0.7f;

                //控制点的画笔
		mClickPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
		mClickPaint.setStyle(Paint.Style.FILL);
		mClickPaint.setColor(Color.parseColor("#C0C0C0"));
	}


	@Override
	protected void onDraw(Canvas canvas) {
		// 移动中心
		canvas.translate(mWidth / 2, mHeight / 2);

		//画色圆, r是半径
		canvas.drawOval(new RectF(-r, -r, r, r), mPaint);
                //画触控点
		canvas.drawCircle(clickX, clickY, 16, mClickPaint);
		super.onDraw(canvas);
	}

        //触摸事件
	@Override
	public boolean onTouchEvent(MotionEvent event) {
                //获取触摸点坐标,看是否在圆内
		float x = event.getX() - mWidth / 2;
		float y = event.getY() - mHeight / 2 + 50;
		boolean inCircle = inColorCircle(x, y, r);
                
                //判断事件
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			downInCircle = inCircle;
			if (downInCircle) {
				clickX = (int) x;
				clickY = (int) y;
				invalidate();
				mListener.onColorChanged(getColor());
			}
		case MotionEvent.ACTION_MOVE:
			if (downInCircle && inCircle) {// down按在渐变色环内, 且move也在渐变色环内
				clickX = (int) x;
				clickY = (int) y;
				invalidate();
				mListener.onColorChanged(getColor());
			}
			break;
		case MotionEvent.ACTION_UP:
			if (downInCircle) {
				downInCircle = false;
				invalidate();
			}
			break;
		}
		return true;
	}

        //测量view的尺寸
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		setMeasuredDimension(mWidth, mHeight);
	}

        //将触摸点的坐标转换成颜色值
	private int getColor() {
		float angle = (float) Math.atan2(clickY, clickX);
		float unit = (float) (angle / (2 * Math.PI));
		if (unit < 0) {
			unit += 1;
		}
		return interpCircleColor(mCircleColors, unit);
	}

	private boolean inColorCircle(float x, float y, float outRadius) {
		double outCircle = Math.PI * outRadius * outRadius;
		// double inCircle = Math.PI * inRadius * inRadius;
		double fingerCircle = Math.PI * (x * x + y * y);
		// && fingerCircle > inCircle
		if (fingerCircle < outCircle) {
			return true;
		} else {
			return false;
		}
	}

	private boolean inCenter(float x, float y, float centerRadius) {
		double centerCircle = Math.PI * centerRadius * centerRadius;
		double fingerCircle = Math.PI * (x * x + y * y);
		if (fingerCircle < centerCircle) {
			return true;
		} else {
			return false;
		}
	}

	//获取圆环上颜色
	private int interpCircleColor(int colors[], float unit) {
		if (unit <= 0) {
			return colors[0];
		}
		if (unit >= 1) {
			return colors[colors.length - 1];
		}

		float p = unit * (colors.length - 1);
		int i = (int) p;
		p -= i;

		// now p is just the fractional part [0...1) and i is the index
		int c0 = colors[i];
		int c1 = colors[i + 1];
		int a = ave(Color.alpha(c0), Color.alpha(c1), p);
		int r = ave(Color.red(c0), Color.red(c1), p);
		int g = ave(Color.green(c0), Color.green(c1), p);
		int b = ave(Color.blue(c0), Color.blue(c1), p);

		return Color.argb(a, r, g, b);
	}


	private int ave(int s, int d, float p) {
		return s + Math.round(p * (d - s));
	}


       //回调接口, 调用的地方需要实现这个接口,响应颜色变化消息
	public interface OnColorChangedListener {
		void onColorChanged(int color);
	}

        //获取listener
	public OnColorChangedListener getColorChangedListener() {
		return mListener;
	}

        //设置颜色变化listener
	public void setColorChangedListener(OnColorChangedListener mListener) {
		this.mListener = mListener;
	}
}


三:在布局文件中使用

 <ColorPickerView
            android:id="@+id/picker"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="visible" />

四:程序中实现接口监听颜色变换

picker.setColorChangedListener(new ColorPickerView.OnColorChangedListener(){
			@Override
			public void onColorChanged(int color) {

			}
		});

五:开源项目的 HoloColorPicker做的很好,可以去github上看下代码

https://github.com/LarsWerkman/HoloColorPicker