圆弧的动画效果实现

需求背景:
画一个app占用的内存图,其中有三个弧,
1、背景全部内存的圈圈;
2、本app占用的内存
3、除app外其他文件占用的大小
进来查看缓存图时,环形需要动态显示
这里写图片描述
技术分析:
从图上看,挺简单的,就三条圆弧,笔宽如图这么大就可以了;
设置三个Paint的不同颜色;
计算所占的比例;
重点以前不懂动态显示圆弧
网上查阅:
主要是利用ObjectAnimator 的ofFloat效果

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "progress",progress)
//progress 的getter和setter

View的代码如下:

package com.github.azhansy.timepickdemo;

import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.DecelerateInterpolator;

/**
 * Created by zhanshuyong on 2017/3/10.
 * 动态的圆环圈
 */
public class CircleProgressBar extends View {

    private RectF rectF;
    private Paint initPaint;
    private Paint backgroundPaint;
    private Paint foregroundPaint;
    private Paint middlePaint;
    private Paint ratesign;
    private int backgroundColor = Color.parseColor("#999999");
    private int middleColor = Color.parseColor("#00a8ff");
    private int foregroundColor = Color.parseColor("#3F51B5");

    /**
     * 进度条以90度角起始(12点方向)
     */
    private int startAngle = -90;
    private float strokeWidth = 74;
    private float background = 0;
    private float progressBackground = 0;
    private float progress = 0;
    private float secondProgress = 0;
    private int min = 0;
    private int max = 100;

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

    public CircleProgressBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        intView(context, attrs, defStyleAttr);
    }

    private void intView(Context context, AttributeSet attrs, int defStyleAttr) {
        rectF = new RectF();
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CircleProgressBar,
                0, 0);
        try {
            strokeWidth = typedArray.getDimension(R.styleable.CircleProgressBar_progressBarThickness, strokeWidth);
            progress = typedArray.getFloat(R.styleable.CircleProgressBar_progress, progress);
            secondProgress = typedArray.getFloat(R.styleable.CircleProgressBar_secondProgress, secondProgress);
            foregroundColor = typedArray.getInt(R.styleable.CircleProgressBar_progressbarColor, foregroundColor);
            middleColor = typedArray.getInt(R.styleable.CircleProgressBar_secondProgressbarColor, middleColor);
            backgroundColor = typedArray.getInt(R.styleable.CircleProgressBar_progressBarBackgroundColor, backgroundColor);
            min = typedArray.getInt(R.styleable.CircleProgressBar_min, min);
            max = typedArray.getInt(R.styleable.CircleProgressBar_max, max);
        } finally {
            typedArray.recycle();
        }

        ratesign = new Paint(Paint.ANTI_ALIAS_FLAG);
        ratesign.setColor(ContextCompat.getColor(getContext(), R.color.progress_rate));
        ratesign.setTextSize(sp2px((float) 17));

        initPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        initPaint.setColor(Color.TRANSPARENT);
        initPaint.setStyle(Paint.Style.STROKE);
        initPaint.setStrokeWidth(strokeWidth);

        backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        backgroundPaint.setColor(backgroundColor);
        backgroundPaint.setStyle(Paint.Style.STROKE);
        backgroundPaint.setStrokeWidth(strokeWidth);

        foregroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        foregroundPaint.setColor(foregroundColor);
        foregroundPaint.setStyle(Paint.Style.STROKE);
        foregroundPaint.setStrokeWidth(strokeWidth);

        middlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        middlePaint.setColor(middleColor);
        middlePaint.setStyle(Paint.Style.STROKE);
        middlePaint.setStrokeWidth(strokeWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawOval(rectF, initPaint);
        float angleBack = 360 * progressBackground / max;
        float angleMiddle = 360 * secondProgress / max;
        float angleFore = 360 * (progress + secondProgress) / max;
        canvas.drawArc(rectF, startAngle, angleBack, false, backgroundPaint);
        canvas.drawArc(rectF, startAngle, angleFore, false, foregroundPaint);
        canvas.drawArc(rectF, startAngle, angleMiddle, false, middlePaint);

//        canvas.drawText(secondProgress + "%", rectF.centerX(), rectF.centerY(), ratesign);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        int min = Math.min(width, height);
        setMeasuredDimension(min, min);
        rectF.set(0 + strokeWidth / 2, 0 + strokeWidth / 2, min - strokeWidth / 2, min - strokeWidth - 2);

    }

    private ObjectAnimator animator1, animator2;


    public void setProgress(float progress) {
        this.progress = progress;
        invalidate();
    }

    public float getSecondProgress() {
        return secondProgress;
    }

    public void setSecondProgress(float secondProgress) {
        this.secondProgress = secondProgress;
        invalidate();
    }

    public float getProgressBackground() {
        return progressBackground;
    }

    public void setProgressBackground(float progressBackground) {
        this.progressBackground = progressBackground;
        invalidate();
    }

    public float getProgress() {
        return progress;
    }

    public void setMax(int max) {
        this.max = max;
        invalidate();
    }

    public void setBackgroundProgressColor(int color) {
        this.backgroundColor = color;
        backgroundPaint.setColor(color);
        invalidate();
        requestLayout();
    }

    public void setMiddleProgessColor(int color) {
        this.middleColor = color;
        middlePaint.setColor(color);
        invalidate();
        requestLayout();
    }

    public void setForegroundProgessColor(int color) {
        this.foregroundColor = color;
        foregroundPaint.setColor(color);
        invalidate();
        requestLayout();
    }

    /**
     * Set the progress with an animation.
     * Note that the {@link ObjectAnimator} Class automatically set the progress
     * so don't call the {@link CircleProgressBar#setProgress(float)} directly within this method.
     *
     * @param progress The progress it should animate to it.
     */
    public void setProgressWithAnimation(float progress) {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "progress", progress);
        objectAnimator.setDuration(500);
        objectAnimator.setInterpolator(new DecelerateInterpolator());
        animator1 = objectAnimator;
//        objectAnimator.start();
    }

    public void setSecondProgressWithAnimation(float progress) {
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "secondProgress", progress);
        objectAnimator.setDuration(500);
        objectAnimator.setInterpolator(new DecelerateInterpolator());
        animator2 = objectAnimator;
        objectAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (animator1 != null) {
                    animator1.start();
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
//        objectAnimator.start();
    }

    public void setProgressBackgroundWithAnimation(float progress) {

        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(this, "progressBackground", progress);
        objectAnimator.setDuration(1000);
        objectAnimator.setInterpolator(new DecelerateInterpolator());
        objectAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if (animator2 != null) {
                    animator2.start();
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        objectAnimator.start();
    }


    private float sp2px(Float sp) {
        float scaleDensity = getContext().getResources().getDisplayMetrics().scaledDensity;
        return sp * scaleDensity;
    }
}

调用方法:

CircleProgressBar circle_bar = (CircleProgressBar) findViewById(R.id.circle_bar);
        circle_bar.setProgressBackgroundWithAnimation(100);
        circle_bar.setSecondProgressWithAnimation(10);
        circle_bar.setProgressWithAnimation(30);

猜你喜欢

转载自blog.csdn.net/azhansy/article/details/61197982