Android 自定义 View 之 圆形 & 方形 进度条

效果

Android 自定义 View 之 圆形 & 方形 进度条_第1张图片
1.gif

实现

圆形进度条
  • attrs

        
        
 
  • CircleProgress.java
/**
 * 圆形进度条
 *
 * @author gavin.xiong 2017/7/18
 */
public class CircleProgress extends View {

    /**
     * 半径
     */
    private int mRadius;
    /**
     * 宽
     */
    private int mWidth;
    /**
     * 高
     */
    private int mHeight;
    /**
     * 高
     */
    private Paint mPaint;
    /**
     * 进度(最大100)
     */
    private float mProgress = 0;

    public CircleProgress(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleProgress);
        mRadius = ta.getDimensionPixelSize(R.styleable.CircleProgress_cpRadius,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 28f, getResources().getDisplayMetrics()));
        int color = ta.getColor(R.styleable.CircleProgress_cpColor, 0x40ffffff);
        ta.recycle();

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(color);
        mPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            mWidth = specSize;
        } else {
            mWidth = defaultRadius() * 2;
        }
        specMode = MeasureSpec.getMode(heightMeasureSpec);
        specSize = MeasureSpec.getSize(heightMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            mHeight = specSize;
        } else {
            mHeight = defaultRadius() * 2;
        }
        setMeasuredDimension(mWidth, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mProgress < 0 || mProgress > 100) {
            return;
        }
        RectF oval = new RectF(mWidth / 2 - mRadius, mHeight / 2 - mRadius, mWidth / 2 + mRadius, mHeight / 2 + mRadius);
        // 根据进度画圆弧 - 反向
        canvas.drawArc(oval, mProgress / 100 * 360 - 90, 360 - mProgress / 100 * 360, true, mPaint);
    }

    /**
     * 设置进度 最大值100
     */
    public void setProgress(float progress) {
        this.mProgress = progress;
        postInvalidate();
    }

    private int defaultRadius() {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 28f, getResources().getDisplayMetrics());
    }
}
方形进度条
  • attrs

        

  • SquareProgress.java
/**
 * 方形进度条
 *
 * @author gavin.xiong 2017/7/22
 */
public class SquareProgress extends View {

    private static final String TAG = "SquareProgress";

    /**
     * 宽
     */
    private int mWidth;
    /**
     * 高
     */
    private int mHeight;
    /**
     * 高
     */
    private Paint mPaint;
    /**
     * 进度(最大100)
     */
    private double mProgress = 0;

    public SquareProgress(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SquareProgress);
        int color = ta.getColor(R.styleable.SquareProgress_spColor, 0x40ffffff);
        ta.recycle();

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(color);
        mPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            mWidth = specSize;
        } else {
            mWidth = defaultLength();
        }
        specMode = MeasureSpec.getMode(heightMeasureSpec);
        specSize = MeasureSpec.getSize(heightMeasureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            mHeight = specSize;
        } else {
            mHeight = defaultLength();
        }
        setMeasuredDimension(mWidth, mHeight);
    }

    private int defaultLength() {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 56f, getResources().getDisplayMetrics());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mProgress < 0 || mProgress >= 100) {
            return;
        }

        // 偏移角度
        double x = mProgress / 100 * 2 * Math.PI;
        double ratio = mWidth * 1D / mHeight;

        Path path = new Path();
        path.moveTo(mWidth / 2, mHeight / 2);

        if (mProgress <= 25) {
            Log.e(TAG, "第一象限");
            if (Math.tan(x) <= ratio) {
                Log.e(TAG, "上横边");
                path.lineTo(mWidth / 2 + (float) Math.tan(x) * mHeight / 2, 0);
                path.lineTo(mWidth, 0);
                path.lineTo(mWidth, mHeight);
                path.lineTo(0, mHeight);
                path.lineTo(0, 0);
                path.lineTo(mWidth / 2, 0);
            } else {
                Log.e(TAG, "上竖边");
                path.lineTo(mWidth, mHeight / 2 - (float) Math.tan(Math.PI / 2 - x) * mWidth / 2);
                path.lineTo(mWidth, mHeight);
                path.lineTo(0, mHeight);
                path.lineTo(0, 0);
                path.lineTo(mWidth / 2, 0);
            }
        } else if (mProgress <= 50) {
            Log.e(TAG, "第二象限");
            if (Math.tan(x - Math.PI / 2) <= 1 / ratio) {
                Log.e(TAG, "下竖边");
                path.lineTo(mWidth, mHeight / 2 + (float) Math.tan(x - Math.PI / 2) * mWidth / 2);
                path.lineTo(mWidth, mHeight);
                path.lineTo(0, mHeight);
                path.lineTo(0, 0);
                path.lineTo(mWidth / 2, 0);
            } else {
                Log.e(TAG, "下横边");
                path.lineTo(mWidth / 2 + (float) Math.tan(Math.PI - x) * mHeight / 2, mHeight);
                path.lineTo(0, mHeight);
                path.lineTo(0, 0);
                path.lineTo(mWidth / 2, 0);
            }
        } else if (mProgress <= 75) {
            Log.e(TAG, "第三象限");
            if (Math.tan(x - Math.PI) <= ratio) {
                Log.e(TAG, "下横边");
                path.lineTo(mWidth / 2 - (float) Math.tan(x - Math.PI) * mHeight / 2, mHeight);
                path.lineTo(0, mHeight);
                path.lineTo(0, 0);
                path.lineTo(mWidth / 2, 0);
            } else {
                Log.e(TAG, "下竖边");
                path.lineTo(0, mHeight / 2 + (float) Math.tan(Math.PI * 3 / 2 - x) * mWidth / 2);
                path.lineTo(0, 0);
                path.lineTo(mWidth / 2, 0);
            }
        } else {
            Log.e(TAG, "第四象限");
            if (Math.tan(x - Math.PI * 3 / 2) <= 1 / ratio) {
                Log.e(TAG, "上竖边");
                path.lineTo(0, mHeight / 2 - (float) Math.tan(x - Math.PI * 3 / 2) * mWidth / 2);
                path.lineTo(0, 0);
                path.lineTo(mWidth / 2, 0);
            } else {
                Log.e(TAG, "上横边");
                path.lineTo(mWidth / 2 - (float) Math.tan(Math.PI * 2 - x) * mHeight / 2, 0);
                path.lineTo(mWidth / 2, 0);
            }
        }

        path.close();
        canvas.drawPath(path, mPaint);
    }

    /**
     * 设置进度 最大值100
     */
    public void setProgress(float progress) {
        this.mProgress = progress;
        postInvalidate();
    }
}

你可能感兴趣的:(Android 自定义 View 之 圆形 & 方形 进度条)