自定义view和属性动画的结合使用

package com.example.admin.customtextview;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

/**
 * Created by admin on 2017/12/12.
 */

public class CustomArc extends View{
    private static final String TAG0 = " yyy ";
    private static final String TAG = " CustomArc ";
    private int default_width = 600;
    private int default_height = 600;
    private int mWidth;
    private int mHeight;
    float radius = default_width/4;//圆圈的半径
    private Paint mPaint;
    private Paint mArcPaint;
    private Paint  mTickPaint;//对勾
    private RectF oval;
    private float sweepAngle ;
    private float startAngle = 0;
    private float mProgress;//进度 0100
    private float mDegrees;//旋转的角度

    float startX,startY,stopX,stopY,middleX,middleY,tickWidth,tickHeight,arrowStartX,arrowStartY,arrowMidX,arrowMidY,arrowEndX,arrowEndY;
    private boolean mIsStartLongTick;
    private float changeTickDegress;
    private String mText;
    private Paint mTextPaint;
    private Integer changeColor;

    public CustomArc(Context context) {
        this(context,null);
    }

    public CustomArc(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CustomArc(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        Log.d(TAG0,TAG+" CustomArc()");
        //外圆圈的画笔
        mPaint = new Paint();
        mPaint.setStrokeWidth(10);
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.parseColor("#BFBFC0"));
        mPaint.setStyle(Paint.Style.STROKE);
        mArcPaint = new Paint();
        mArcPaint.setStrokeWidth(10);
        mArcPaint.setAntiAlias(true);
        mArcPaint.setColor(Color.BLUE);
        mArcPaint.setStyle(Paint.Style.STROKE);

        //对勾的画笔
        mTickPaint = new Paint();
        mTickPaint.setStrokeWidth(10);
        mTickPaint.setAntiAlias(true);
        mTickPaint.setColor(Color.parseColor("#BFBFC0"));
        mTickPaint.setStyle(Paint.Style.STROKE);
        mTickPaint.setStrokeJoin(Paint.Join.ROUND);
        mTickPaint.setDither(true);
        oval = new RectF();

        mText = "i am text";
        mTextPaint = new Paint();
        mTextPaint.setColor(Color.BLUE);
        mTextPaint.setAntiAlias(true);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d(TAG0,TAG+" onDraw()");

        //画最外层圆圈,空心描边
        drawOutSideCircle(canvas);
        //画进度圆弧,空心,描边
        drawArcProgress(canvas);
        //画一个对勾路径
        drawTick(canvas);
        //画文字
        drawText(canvas);

    }

    private void drawText(Canvas canvas) {
        float mMeasureText = mTextPaint.measureText(mText);
        mTextPaint.setStrokeWidth(10);
        mTextPaint.setTextSize(16);
        canvas.drawText(mText,mWidth/2 - mMeasureText/2,mHeight/2+radius+mMeasureText,mTextPaint);

    }

    private void drawTick(Canvas canvas) {
        tickWidth = radius/2;
        tickHeight = radius/2;
        startX = mWidth/2 - tickWidth/2;
        startY = mWidth/2 + tickHeight/2;

        middleX = mWidth/2 ;
        middleY = mWidth/2 - tickHeight/2;

        stopX = middleX + tickWidth/2;
        stopY = middleY + tickHeight;

        arrowStartX = mWidth/2+radius*3/4;
        arrowStartY = mWidth/2-radius*1/4;

        arrowMidX = mWidth/2+radius;
        arrowMidY = mHeight/2;

        arrowEndX = arrowMidX+radius*1/4;
        arrowEndY = arrowMidY-radius*1/4;
        if(mIsStartLongTick) {
            startX-=mProgress/5;
            startY+=mProgress/5;
            mTickPaint.setColor(Color.BLUE);

        }

        mDegrees = mProgress*3.6f;
        canvas.save();
        canvas.rotate(mDegrees,mWidth/2,mWidth/2);//180度旋转
        canvas.rotate(changeTickDegress,mWidth/2,mWidth/2);//一定要先于目的view的绘制调用,才能让目的view跟着一起动;360        Path path = new Path();
        path.moveTo(startX,startY);
        path.lineTo(middleX,middleY);
        path.lineTo(stopX,stopY);
        canvas.drawPath(path,mTickPaint);

      /*
       一个绕着圆圈转的箭头
       Path arrowPath = new Path();
        arrowPath.moveTo(arrowStartX,arrowStartY);
        arrowPath.lineTo(arrowMidX,arrowMidY);
        arrowPath.lineTo(arrowEndX,arrowEndY);
        canvas.drawPath(arrowPath,mTickPaint);*/

        canvas.restore();//一定记得还原画布,否则在它之后的view也会跟着转动
    }

    private void drawOutSideCircle(Canvas canvas) {
        canvas.drawCircle(mWidth/2,mHeight/2,radius,mPaint);
    }

    private void drawArcProgress(Canvas canvas) {
        if(changeColor != null) {
            mArcPaint.setColor((int) changeColor);
        }
        sweepAngle = mProgress * 3.6f;
        oval.set(mWidth/2-radius,mWidth/2-radius,mWidth/2+radius,mWidth/2+radius);

        canvas.drawArc(oval,startAngle, sweepAngle,false,mArcPaint);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.d(TAG0,TAG+" onMeasure()");
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
        int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
        int width,height;
        if(widthMode == MeasureSpec.EXACTLY) {
            width = measureWidth;
        }else {
            width = default_width;
        }

        if(heightMode == MeasureSpec.EXACTLY) {
            height = measureHeight;
        }else {
            height = default_height;
        }

        setMeasuredDimension(width,height);

    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        Log.d(TAG0,TAG+" onLayout() mWidth = "+mWidth+" mHeight ="+mHeight +" changed = "+changed+" left = "+left+" top = "+top+" right = "+right+" bottom = "+bottom);
        mWidth = getWidth();
        mHeight = getHeight();
        radius = mWidth/4;
    }

    public void startAnim() {
       /* 1.ValueAnimator va = ValueAnimator.ofFloat(0,100,0);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mProgress = (float) animation.getAnimatedValue();
                Log.d(TAG0, TAG + " mProgress = " + mProgress);
                postInvalidate();
            }});
        va.setRepeatCount(0);
        va.setRepeatMode(ValueAnimator.RESTART);
        va.setDuration(5000);
        va.start();*/
        //2.1可以起到同样的作用
       ValueAnimator va = ValueAnimator.ofObject(new MyObjTypeEva(),0.0f,100f);
        va.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                Log.d(TAG0,TAG+"ValueAnimator.ofObject(): onAnimationEnd() :mProgress = "+mProgress);
                start180Anim();
            }
        });
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mProgress = (float) animation.getAnimatedValue();
                mText = mProgress+"%";
                Log.d(TAG0,TAG+" onAnimationUpdate() :mProgress = "+mProgress);
                postInvalidate();
            }

        });
        va.setDuration(5000);
        va.setRepeatCount(0);
        va.start();
        startColorAnim();//颜色渐变的属性动画
    }

    private void start180Anim() {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f,180f);
        valueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                Log.d(TAG0,TAG+" start180Anim():onAnimationUpdate() :mProgress = "+mProgress);
                mIsStartLongTick = true;
                mText = "完成";
                postInvalidate();
            }
        });
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                changeTickDegress = (float) animation.getAnimatedValue();

                postInvalidate();
            }
        });
        valueAnimator.setDuration(2000);
        valueAnimator.start();
        valueAnimator.setRepeatCount(0);
    }

    class MyObjTypeEva implements TypeEvaluator {

        /**
         *
         * @param fraction 01之间,表示当前动画的速率
         * @param startValue 动画起始值
         * @param endValue 动画结束值
         * @return
         */
        @Override
        public Object evaluate(float fraction, Object startValue, Object endValue) {
            float fEndValue = (float) endValue;
            float fStartValue = (float) startValue;
            Log.d(TAG0,TAG+" evaluate() :fraction = "+fraction+" fStartValue = "+fStartValue+" fEndValue = "+fEndValue);
            return fraction*(fEndValue - fStartValue);
        }
    }

    public void startColorAnim() {
        ValueAnimator va = ValueAnimator.ofArgb(0xffffffff,0xffff0000,0xff0000ff);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                changeColor = (Integer) animation.getAnimatedValue();
                Log.d(TAG0,TAG+" onAnimationUpdate():changeColor = "+changeColor);
                postInvalidate();
            }
        });
        va.setDuration(5000);
        va.setRepeatCount(0);
        va.start();
    }
}
此view实现了一个带进度的圆弧,max是360,中间伴随着颜色的变化,以及画路径方法的使用,知识点比较多,详情,看代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值