圆形倒计时

效果

在这里插入图片描述
Github传送门 https://github.com/drkingwater/CountDownView

思路

1、Path添加圆环
2、获取圆环长度
3、利用属性动画从0-1百分比和PathMeasure.getSegment获取圆环的一部分
4、画出这部分圆环
5、画数字文本

实现

package com.pxq.myapplication.widget;

import android.animation.AnimatorSet;
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.PathMeasure;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

public class CountDownView extends View {

    private static final String TAG = "CountDownView";

    private Paint mPaint, mTextPaint;

    private Path mPath, mDstPath;
    private PathMeasure mPathMeasure;

    private int mStrokeWidth = 15;

    private float mPathLength = 0;

    private float mDelta = 0f;

    private int mCount = 5;
    private int mCurrentCount = mCount;

    private Rect mTextRect;

    public CountDownView(Context context) {
        super(context);
        init();
    }

    public CountDownView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CountDownView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mStrokeWidth);
        mPaint.setColor(Color.RED);
        mPaint.setAntiAlias(true);

        mTextPaint = new TextPaint();
        mTextPaint.setColor(Color.BLACK);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(100);

        mPath = new Path();
        mDstPath = new Path();
        mPathMeasure = new PathMeasure();

        mTextRect = new Rect();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mPath.reset();
        int radius= w > h ? h : w;
        //圆环
        mPath.addCircle(getWidth() / 2, getHeight() / 2, (radius- mStrokeWidth) / 2, Path.Direction.CW);
        mPathMeasure.setPath(mPath, false);
        //获取圆的长度
        mPathLength = mPathMeasure.getLength();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //动态计算剩余路径长度
        mPathMeasure.getSegment(mPathLength * mDelta, mPathLength, mDstPath, true);
        canvas.save();
        //画布逆时针旋转90度
        canvas.rotate(-90, getWidth() / 2, getHeight() / 2);
        //画圆
        canvas.drawPath(mDstPath, mPaint);
        mDstPath.reset();
        canvas.restore();
        //draw text
        mTextPaint.setColor(Color.BLACK);
        //计算文本宽高
        getTextBounds(mCurrentCount);
        canvas.drawText(String.valueOf(mCurrentCount), (getWidth() - mTextRect.width()) / 2, (getHeight() + mTextRect.height()) / 2, mTextPaint);
        mTextPaint.setColor(Color.RED);
    }

    private void getTextBounds(int count) {
        mTextPaint.getTextBounds(String.valueOf(count), 0, String.valueOf(count).length(), mTextRect);
    }

    public void setCount(int count) {
        mCount = count;
        startAnim();
    }

    private void startAnim() {
        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        ValueAnimator countAnimator = ValueAnimator.ofInt(mCount, 0);
        //用来倒计时
        countAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int value = (int) animation.getAnimatedValue();
//                Log.e(TAG, "onAnimationUpdate: " + value);
                mCurrentCount = value;
            }
        });
        //用来更新圆的长度
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mDelta = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        AnimatorSet set = new AnimatorSet();
        set.play(valueAnimator)
                .with(countAnimator);
        set.setDuration(mCount * 1000);
        set.setInterpolator(new LinearInterpolator());
        set.start();
    }
}

为了实现倒计时,直接用属性动画了,还没想到别的方法。

发布了19 篇原创文章 · 获赞 25 · 访问量 5601

猜你喜欢

转载自blog.csdn.net/pxq10422/article/details/96584699