自定义一款圆形带渐变色的progress

自定义一款圆形带渐变色的progress

如上图的圆形的progressbar,不仅带有渐变色,还有在起止点都有一个小圆点,那么怎么实现呢?

首先,考虑这肯定得自定义了;

然后看他的组成部分,有三个,底下亮灰色的圆环,一个带渐变色的弧线,还有弧线起止点的圆点;

最后就是继承View,使用paint开始画了,以下是源码,一些自定义属性就不上传了,就三个,自己定义以下就好:

package com.*.component.views;

import android.content.Context;
import android.content.res.TypedArray;
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.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.*.component.R;

/**
 * Created by Qile on 2018/12/12
 */
public class CustomProgress extends View {

    private Paint mPaint;
    private Paint mPointPaint;
    private Paint mCirclePaint;
    private int startColor;
    private int centerColor;
    private int endColor;
    private int offSet = 40;
    private float pointX;
    private float pointY;
    private float pointR = 10;
    private float mSweepAngle = 180;
    private float mStartAngle = -90;

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

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

    public CustomProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CustomProgress);
        startColor = ta.getColor(R.styleable.CustomProgress_progressCusStartColor, context.getResources().getColor(R.color.dark_blue));
        centerColor = ta.getColor(R.styleable.CustomProgress_progressCusCenterColor, context.getResources().getColor(R.color.white));
        endColor = ta.getColor(R.styleable.CustomProgress_progressCusEndColor, context.getResources().getColor(R.color.green));
        ta.recycle();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPointPaint = new Paint();
        mPointPaint.setAntiAlias(true);
        mCirclePaint = new Paint();
        mCirclePaint.setAntiAlias(true);
    }

    private int width;
    private int height;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = measureDimension(200, widthMeasureSpec);
        height = measureDimension(200, heightMeasureSpec);
        setMeasuredDimension(width, height);

    }

    private int measureDimension(int defaultValue, int measureSpec) {
        int result = 0;

        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = defaultValue;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(defaultValue, specSize);
            }
        }
        return result;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(10);
        int[] colors = {startColor, centerColor, endColor};

        mPointPaint.setColor(startColor);
        mPointPaint.setStyle(Paint.Style.FILL);

        mCirclePaint.setColor(Color.LTGRAY);
        mCirclePaint.setStyle(Paint.Style.STROKE);
        mCirclePaint.setStrokeWidth(10);


        RectF rectF = new RectF(offSet, offSet, width - offSet, height - offSet);
        LinearGradient lg = new LinearGradient(offSet, offSet, width - offSet, height - offSet, colors, null, Shader.TileMode.MIRROR);
        mPaint.setShader(lg);

        canvas.drawCircle(width / 2, height / 2, width / 2 - offSet, mCirclePaint);

        canvas.drawArc(rectF, mStartAngle, mSweepAngle, false, mPaint);

        canvas.drawCircle(getPointX(width / 2, mStartAngle, width / 2 - pointR),
                getPointY(height / 2, mStartAngle, width / 2 - pointR), pointR, mPointPaint);

        mPointPaint.setColor(endColor);
        pointX = getPointX(width / 2, mSweepAngle + mStartAngle, width / 2 - pointR);
        pointY = getPointY(height / 2, mSweepAngle + mStartAngle, width / 2 - pointR);
        canvas.drawCircle(pointX, pointY, pointR, mPointPaint);

    }

    private float getPointY(int circleY, float sweepAngle, float circleR) {
        return circleY + circleR * (float) Math.sin(sweepAngle * Math.PI / 180);
    }

    private float getPointX(int circleX, float sweepAngle, float circleR) {
        return circleX + circleR * (float) Math.cos(sweepAngle * Math.PI / 180);
    }

    public void setProgress(int progress, int max) {
        setProgressWithAngle(-90f, progress, max);
    }

    public void setProgressWithAngle(float startAngle, int progress, int max) {
        mStartAngle = startAngle;
        mSweepAngle = 360 * (progress / max);
        invalidate();
    }
}