自定义颜色控件の颜色采集View

来源:互联网 发布:polyfit函数在c语言 编辑:程序博客网 时间:2024/05/16 17:20

自定义的View,效果图如下所示
效果图

在自定义View中,除去padding,宽高比例是1:1.1,如果宽度设定好,高度值无效。如果宽度为未确定,按照高度值设定。
对外接口:setOnColorChangedListener()

package com.android.demo;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.LinearGradient;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Shader;import android.graphics.SweepGradient;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;/** * 取色环控件,中间为当前颜色,触摸外环和矩形框内改变当前颜色,抬起通过接口传递数据。 * 控制高:宽比例为:1.1:1。 * Created by wu on 2015/12/18. */public class ColorPickerView extends View {    private final boolean debug = true;    private final String TAG = "ColorPicker";    private OnColorChangedListener mListener;    private Paint mPaint;// 渐变色环画笔    private Paint mCenterPaint;// 中间圆画笔    private Paint mLinePaint;// 分隔线画笔    private Paint mRectPaint;// 渐变方块画笔    private Shader rectShader;// 渐变方块渐变图像    private float rectLeft;// 渐变方块左x坐标    private float rectTop;// 渐变方块右x坐标    private float rectRight;// 渐变方块上y坐标    private float rectBottom;// 渐变方块下y坐标    private int[] mCircleColors;// 渐变色环颜色    private int[] mRectColors;// 渐变方块颜色    private int mInitialColor;//初始颜色    private int mHeight;// View高    private int mWidth;// View宽    private float r;// 色环半径(paint中部)    private float centerRadius;// 中心圆半径    private boolean downInCircle = true;// 按在渐变环上    private boolean downInRect;// 按在渐变方块上    private boolean highlightCenter;// 高亮    private boolean highlightCenterLittle;// 微亮    public ColorPickerView(Context context) {        this(context, null);    }    public ColorPickerView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public ColorPickerView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    public void init() {        // 渐变色环参数        mCircleColors = new int[]{0xFFFF0000, 0xFFFF00FF, 0xFF0000FF,                0xFF00FFFF, 0xFF00FF00, 0xFFFFFF00, 0xFFFF0000};        Shader s = new SweepGradient(0, 0, mCircleColors, null);        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setShader(s);        mPaint.setStyle(Paint.Style.STROKE);        mPaint.setStrokeWidth(70);        mInitialColor = 0xFFFF0000;        // 中心圆参数        mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mCenterPaint.setColor(mInitialColor);        mCenterPaint.setStrokeWidth(5);        // 边框参数        mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mLinePaint.setColor(Color.parseColor("#72A1D1"));        mLinePaint.setStrokeWidth(4);        // 黑白渐变参数        mRectColors = new int[]{0xFF000000, mCenterPaint.getColor(),                0xFFFFFFFF};        mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mRectPaint.setStrokeWidth(5);    }    @Override    protected void onDraw(Canvas canvas) {        // 移动中心        int widthTrans=(mWidth-getPaddingLeft()-getPaddingRight())/2+getPaddingLeft();        int heightTrans=(mWidth-getPaddingLeft()-getPaddingRight()) / 2+getPaddingTop();        canvas.translate(widthTrans,heightTrans);        // 画中心圆        canvas.drawCircle(0, 0, centerRadius, mCenterPaint);        // 是否显示中心圆外的小圆环        if (highlightCenter || highlightCenterLittle) {            int c = mCenterPaint.getColor();            mCenterPaint.setStyle(Paint.Style.STROKE);            if (highlightCenter) {                mCenterPaint.setAlpha(0xFF);            } else if (highlightCenterLittle) {                mCenterPaint.setAlpha(0x90);            }            canvas.drawCircle(0, 0,                    centerRadius + mCenterPaint.getStrokeWidth(), mCenterPaint);            mCenterPaint.setStyle(Paint.Style.FILL);            mCenterPaint.setColor(c);        }        // 画色环        canvas.drawOval(new RectF(-r, -r, r, r), mPaint);        // 画黑白渐变块        if (downInCircle) {            mRectColors[1] = mCenterPaint.getColor();        }        rectShader = new LinearGradient(rectLeft, 0, rectRight, 0, mRectColors,                null, Shader.TileMode.MIRROR);        mRectPaint.setShader(rectShader);        canvas.drawRect(rectLeft, rectTop, rectRight, rectBottom, mRectPaint);        float offset = mLinePaint.getStrokeWidth() / 2;        canvas.drawLine(rectLeft - offset, rectTop - offset * 2, rectLeft                - offset, rectBottom + offset * 2, mLinePaint);// 左        canvas.drawLine(rectLeft - offset * 2, rectTop - offset, rectRight                + offset * 2, rectTop - offset, mLinePaint);// 上        canvas.drawLine(rectRight + offset, rectTop - offset * 2, rectRight                + offset, rectBottom + offset * 2, mLinePaint);// 右        canvas.drawLine(rectLeft - offset * 2, rectBottom + offset, rectRight                + offset * 2, rectBottom + offset, mLinePaint);// 下        super.onDraw(canvas);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        int widthTrans=(mWidth-getPaddingLeft()-getPaddingRight())/2+getPaddingLeft();        int heightTrans=(mWidth-getPaddingLeft()-getPaddingRight()) / 2+getPaddingTop();        float x = event.getX() - widthTrans;        float y = event.getY() - heightTrans;        boolean inCircle = inColorCircle(x, y, r + mPaint.getStrokeWidth() / 2,                r - mPaint.getStrokeWidth() / 2);        boolean inCenter = inCenter(x, y, centerRadius);        boolean inRect = inRect(x, y);        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                downInCircle = inCircle;                downInRect = inRect;                highlightCenter = inCenter;            case MotionEvent.ACTION_MOVE:                if (downInCircle && inCircle) {// down按在渐变色环内, 且move也在渐变色环内                    float angle = (float) Math.atan2(y, x);                    float unit = (float) (angle / (2 * Math.PI));                    if (unit < 0) {                        unit += 1;                    }                    mCenterPaint.setColor(interpCircleColor(mCircleColors, unit));                    if (debug)                        Log.v(TAG, "色环内, 坐标: " + x + "," + y);                } else if (downInRect && inRect) {// down在渐变方块内, 且move也在渐变方块内                    mCenterPaint.setColor(interpRectColor(mRectColors, x));                }                if (debug)                    Log.v(TAG, "[MOVE] 高亮: " + highlightCenter + "微亮: "                            + highlightCenterLittle + " 中心: " + inCenter);                if ((highlightCenter && inCenter)                        || (highlightCenterLittle && inCenter)) {// 点击中心圆, 当前移动在中心圆                    highlightCenter = true;                    highlightCenterLittle = false;                } else if (highlightCenter || highlightCenterLittle) {// 点击在中心圆,                    // 当前移出中心圆                    highlightCenter = false;                    highlightCenterLittle = true;                } else {                    highlightCenter = false;                    highlightCenterLittle = false;                }                invalidate();                break;            case MotionEvent.ACTION_UP:            /*if (highlightCenter && inCenter) {// 点击在中心圆, 且当前启动在中心圆                if (mListener != null) {                    mListener.colorChanged(mCenterPaint.getColor());                }            }*/                if (inCircle || inRect) {                    if (mListener != null) {                        mListener.colorChanged(mCenterPaint.getColor());                    }                }                if (downInCircle) {                    downInCircle = false;                }                if (downInRect) {                    downInRect = false;                }                if (highlightCenter) {                    highlightCenter = false;                }                if (highlightCenterLittle) {                    highlightCenterLittle = false;                }                invalidate();                break;        }        return true;    }    /**     * 坐标是否在色环上     *     * @param x         坐标     * @param y         坐标     * @param outRadius 色环外半径     * @param inRadius  色环内半径     * @return     */    private boolean inColorCircle(float x, float y, float outRadius,                                  float inRadius) {        double outCircle = Math.PI * outRadius * outRadius;        double inCircle = Math.PI * inRadius * inRadius;        double fingerCircle = Math.PI * (x * x + y * y);        if (fingerCircle < outCircle && fingerCircle > inCircle) {            return true;        } else {            return false;        }    }    /**     * 坐标是否在中心圆上     *     * @param x            坐标     * @param y            坐标     * @param centerRadius 圆半径     * @return     */    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;        }    }    /**     * 坐标是否在渐变色中     *     * @param x     * @param y     * @return     */    private boolean inRect(float x, float y) {        if (x <= rectRight && x >= rectLeft && y <= rectBottom && y >= rectTop) {            return true;        } else {            return false;        }    }    /**     * 获取圆环上颜色     *     * @param colors     * @param unit     * @return     */    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);    }    /**     * 获取渐变块上颜色     *     * @param colors     * @param x     * @return     */    private int interpRectColor(int colors[], float x) {        int a, r, g, b, c0, c1;        float p;        if (x < 0) {            c0 = colors[0];            c1 = colors[1];            p = (x + rectRight) / rectRight;        } else {            c0 = colors[1];            c1 = colors[2];            p = x / rectRight;        }        a = ave(Color.alpha(c0), Color.alpha(c1), p);        r = ave(Color.red(c0), Color.red(c1), p);        g = ave(Color.green(c0), Color.green(c1), p);        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));    }    /**     * 设定宽高比例     * @param widthMeasureSpec     * @param heightMeasureSpec     */    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int width=widthSize-getPaddingLeft()-getPaddingRight();        int height=heightSize-getPaddingTop()-getPaddingBottom();        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        if (widthMode == MeasureSpec.EXACTLY) {            height = (int) (width * 1.1f + 0.5f);        } else if (heightMode == MeasureSpec.EXACTLY) {            width = (int) (height / 1.1f + 0.5f);        }        widthMeasureSpec = MeasureSpec.makeMeasureSpec(width+getPaddingLeft()+getPaddingRight(), MeasureSpec.EXACTLY);        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height+getPaddingTop()+getPaddingBottom(), MeasureSpec.EXACTLY);        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);    }    /**     * 重新设定圆环半径、中心圆半径以及矩形位置     * @param w     * @param h     * @param oldw     * @param oldh     */    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        this.mHeight = h;        this.mWidth = w;        int width=mWidth-getPaddingLeft()-getPaddingRight();        int height=mHeight-getPaddingTop()-getPaddingBottom();        mPaint.setStrokeWidth(width/2*0.8f*0.2f);//外圆环的宽度根据设定的宽高进行调整        r = width / 2 * 0.8f - mPaint.getStrokeWidth() * 0.5f;        rectLeft = -r - mPaint.getStrokeWidth() * 0.5f;        rectRight = r + mPaint.getStrokeWidth() * 0.5f;        rectTop = width / 2 - mLinePaint.getStrokeMiter() * 0.5f-0.05f*width;        rectBottom = height - width / 2 - mLinePaint.getStrokeMiter()-0.05f*width;        centerRadius = (r - mPaint.getStrokeWidth() / 2) * 0.5f;        invalidate();    }    /**     * 设定中心色     * @param mInitialColor     */    public void setInitialColor(int mInitialColor) {        mCenterPaint.setColor(mInitialColor);    }    /**     * 设定回调接口     * @param listener     */    public void setOnColorChangedListener(OnColorChangedListener listener) {        mListener = listener;    }    /**     * 回调接口     */    public interface OnColorChangedListener {        /**         * 回调函数         *         * @param color 选中的颜色         */        void colorChanged(int color);    }}
0 0
原创粉丝点击