美文网首页自定义views
一个简单的自定义view

一个简单的自定义view

作者: ChangQin | 来源:发表于2017-10-25 15:19 被阅读163次

    参考自http://www.jianshu.com/p/1b2cdba03d23

    public class CheckView extends View {
        private Context mContext;
        //圆环画笔
        private Paint mPaintRing;
        //对号画笔
        private Paint mPaintTick;
        //圆的画笔
        private Paint mPaintCircle;
    
        private int unCheckBaseColor;
        private int checkBaseColor;
        private int checkTickColor;
        private RectF mRectF = new RectF();
        private float centerX, centerY;
        private float[] mPoints = new float[8];
        private boolean mIsChecked;
        private int radius;
        private float tickRadius;
        private float tickRadiusOffset;
    
        private int ringProgress = 0;
        private int circleProgress = 0;
        private int rightAlpha = 0;
        private boolean IsAnimeRuning;
        private boolean ringAnimeEnd;
    
        private OnCheckChangeListener mCheckChangeListener;
        public CheckView(Context context) {
            this(context, null);
        }
    
        public CheckView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public CheckView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mContext = context;
            init(attrs);
            initPaint();
            setClickEvent();
        }
    
        private void initPaint() {
            mPaintRing = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaintRing.setStyle(Paint.Style.STROKE);
            mPaintRing.setColor(mIsChecked ? checkBaseColor : unCheckBaseColor);
            mPaintRing.setStrokeWidth(dp2px(mContext, 2.5f));
            mPaintRing.setStrokeCap(Paint.Cap.ROUND);
    
            mPaintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaintCircle.setColor(checkTickColor);
            mPaintCircle.setStrokeWidth(dp2px(mContext, 1));
    
            mPaintTick = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaintTick.setColor(mIsChecked ? checkTickColor : unCheckBaseColor);
            mPaintTick.setStyle(Paint.Style.STROKE);
            mPaintTick.setStrokeCap(Paint.Cap.ROUND);
            mPaintTick.setStrokeWidth(dp2px(mContext, 2.5f));
        }
    
        private void init(AttributeSet attrs) {
            TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.CheckView);
            unCheckBaseColor = a.getColor(R.styleable.CheckView_uncheck_color, getResources().getColor(R.color.tick_gray));
            checkBaseColor = a.getColor(R.styleable.CheckView_check_color, getResources().getColor(R.color.tick_yellow));
            checkTickColor = a.getColor(R.styleable.CheckView_check_right_color, getResources().getColor(R.color.tick_white));
    
            a.recycle();
            radius = dp2px(mContext, 30);
            tickRadius = dp2px(mContext, 12);
            tickRadiusOffset = dp2px(mContext, 4);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            int width = getMySize(radius * 2, widthMeasureSpec);
            int height = getMySize(radius * 2, heightMeasureSpec);
    
            int res = Math.max(width, height);
    
            setMeasuredDimension(res, res);
    
            centerX = getMeasuredWidth() / 2;
            centerY = getMeasuredHeight() / 2;
    
            mRectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
    
    
            //设置打钩的几个点坐标
            mPoints[0] = centerX - tickRadius + tickRadiusOffset;
            mPoints[1] = (float) centerY;
            mPoints[2] = centerX - tickRadius / 2 + tickRadiusOffset;
            mPoints[3] = centerY + tickRadius / 2;
            mPoints[4] = centerX - tickRadius / 2 + tickRadiusOffset;
            mPoints[5] = centerY + tickRadius / 2;
            mPoints[6] = centerX + tickRadius * 2 / 4 + tickRadiusOffset;
            mPoints[7] = centerY - tickRadius * 2 / 4;
        }
    
    
        @Override
        protected void onDraw(final Canvas canvas) {
            super.onDraw(canvas);
    
            if (!mIsChecked) {
                canvas.drawArc(mRectF, 90, 360, false, mPaintRing);
                canvas.drawLines(mPoints, mPaintTick);
                return;
            }
            if (ringAnimeEnd){
                mPaintCircle.setColor(checkBaseColor);
                //画满黄色的圆
                canvas.drawCircle(centerX,centerY,radius,mPaintCircle);
                mPaintCircle.setColor(checkTickColor);
            }
            //画圆环
            canvas.drawArc(mRectF, 90, ringProgress, false, mPaintRing);
            //画逐渐缩小的白圆
            canvas.drawCircle(centerX,centerY,radius-circleProgress,mPaintCircle);
            //画对号
            mPaintTick.setAlpha(rightAlpha);
            canvas.drawLines(mPoints,mPaintTick);
            if (!IsAnimeRuning) {
                IsAnimeRuning = true;
                ObjectAnimator ringAnimator = ObjectAnimator.ofInt(this,"ringProgress",0,360);
                ObjectAnimator circleAnimator = ObjectAnimator.ofInt(this,"circleProgress",0,radius);
                ObjectAnimator rightAnimator = ObjectAnimator.ofInt(this,"rightAlpha",0,255);
                ringAnimator.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        ringAnimeEnd = true;
                    }
                });
                PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 1f,1.2f,1f);
                PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleY", 1f,1.2f,1f);
                ObjectAnimator scaleAnimator = ObjectAnimator.ofPropertyValuesHolder(this, holder1, holder2);
                AnimatorSet animatorSet = new AnimatorSet();
                animatorSet.playSequentially(ringAnimator,circleAnimator,rightAnimator,scaleAnimator);
                animatorSet.start();
            }
        }
    
    
    
        private void reset() {
            initPaint();
            ringProgress = 0;
            circleProgress = 0;
            rightAlpha = 0;
            IsAnimeRuning = false;
            ringAnimeEnd = false;
            mRectF.set(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
    
            invalidate();
        }
    
        private void setClickEvent() {
            this.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    mIsChecked = !mIsChecked;
                    reset();
                    if (mCheckChangeListener!=null){
                        mCheckChangeListener.onCheckChange((TestTickView)v,mIsChecked);
                    }
                }
            });
        }
    
        //用于属性动画的getter和setter
        public int getRingProgress() {
            return ringProgress;
        }
        public void setRingProgress(int ringProgress) {
            this.ringProgress = ringProgress;
            invalidate();
        }
        public int getCircleProgress() {
            return circleProgress;
        }
        public void setCircleProgress(int circleProgress) {
            this.circleProgress = circleProgress;
            invalidate();
        }
    
        public int getRightAlpha() {
            return rightAlpha;
        }
    
        public void setRightAlpha(int rightAlpha) {
            this.rightAlpha = rightAlpha;
            invalidate();
        }
    
        private int getMySize(int defSize, int measureSpec) {
            int result;
            int mode = MeasureSpec.getMode(measureSpec);
            int size = MeasureSpec.getSize(measureSpec);
    
            if (mode == MeasureSpec.UNSPECIFIED || mode == MeasureSpec.AT_MOST) {
                result = defSize;
            } else {
                result = size;
            }
            return result;
        }
    
        private static int dp2px(Context context, float dpValue) {
            final float scale = context.getResources().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }
    
        public void setCheckChangeListener(OnCheckChangeListener checkChangeListener) {
            mCheckChangeListener = checkChangeListener;
        }
    
        public interface OnCheckChangeListener{
            void onCheckChange(TestTickView testTickView,boolean checked);
        }
    }
    
    <declare-styleable name="CheckView">
            <attr name="uncheck_color" format="color" />
            <!--选中后的基调颜色-->
            <attr name="check_color" format="color" />
            <!--选中后钩的颜色-->
            <attr name="check_right_color" format="color" />
            <!--圆的半径-->
            <attr name="radius_size" format="dimension" />
    </declare-styleable>
    

    相关文章

      网友评论

      本文标题:一个简单的自定义view

      本文链接:https://www.haomeiwen.com/subject/zuvqpxtx.html