自定义view之圆形进度条

最近在练习自定义view,看了很多demo,关于自定义圆形进度条基本上大同小异。第一步先画一个背景圆,然后在背景圆的基础上画圆弧,圆弧画笔的宽度要和背景圆的画笔宽度一样,然后添加一个ValueAnimator动画进行重绘,来实现动画效果。效果图如下
这里写图片描述

画背景圆

  mArcRectF.set(mArcWidth / 2, mArcWidth / 2, getWidth() - mArcWidth / 2, getHeight() - mArcWidth / 2);
        //画背景弧线
        canvas.drawArc(mArcRectF, -90, 360, false, mArcBackPaint);

画圆弧

 //画百分比值弧线
        canvas.drawArc(mArcRectF, -90, mSweepAngle, false, mArcForePaint);

attrs文件

<declare-styleable name="MyCircularProgressView">
        <attr name="arcWidth" format="dimension" />
        <attr name="scaleCount" format="integer" />
        <attr name="startColor" format="color" />
        <attr name="endColor" format="color" />
        <attr name="labelText" format="string" />
        <attr name="textColor" format="color" />
        <attr name="progressTextSize" format="dimension" />
        <attr name="labelTextSize" format="dimension" />
    </declare-styleable>

完整代码


public class MyCircularProgressView extends View {
    /* 弧线宽度 */
    private float mArcWidth;
    /* 渐变起始颜色 */
    private int mStartColor;
    /* 渐变终止颜色 */
    private int mEndColor;
    /* 渐变颜色数组 */
    private int[] mColorArray;
    /* 标签说明文本 */
    private String mLabelText;
    /* 文本颜色 */
    private int mTextColor;
    /* 百分比文本字体大小 */
    private float mProgressTextSize;
    /* 标签说明字体大小 */
    private float mLabelTextSize;
    /* 背景弧线画笔 */
    private Paint mArcBackPaint;
    /* 百分比值弧线画笔 */
    private Paint mArcForePaint;
    /* 刻度线画笔 */
    private Paint mLinePaint;
    /* 标签说明文本画笔 */
    private Paint mLabelTextPaint;
    /* 百分比文本画笔 */
    private Paint mProgressTextPaint;
    /* 弧线外切矩形 */
    private RectF mArcRectF;
    /* 测量文本宽高的矩形 */
    private Rect mTextRect;
    /* 百分比 */
    private float mProgress;
    /* 百分比对应角度 */
    private float mSweepAngle;
    public MyCircularProgressView(Context context) {
        this(context, null);
    }
    public MyCircularProgressView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public MyCircularProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyCircularProgressView, defStyleAttr, 0);
        mArcWidth = ta.getDimension(R.styleable.MyCircularProgressView_arcWidth, DensityUtils.dp2px(context, 8));
        mStartColor = ta.getColor(R.styleable.MyCircularProgressView_startColor, Color.parseColor("#3FC199"));
        mEndColor = ta.getColor(R.styleable.MyCircularProgressView_endColor, Color.parseColor("#3294C1"));
        mColorArray = new int[]{mStartColor, mEndColor};
        mLabelText = ta.getString(R.styleable.MyCircularProgressView_labelText);
        mTextColor = ta.getColor(R.styleable.MyCircularProgressView_textColor, Color.parseColor("#4F5F6F"));
        mProgressTextSize = ta.getDimension(R.styleable.MyCircularProgressView_progressTextSize, 160);
        mLabelTextSize = ta.getDimension(R.styleable.MyCircularProgressView_labelTextSize, 64);
        ta.recycle();
        mArcBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mArcBackPaint.setStyle(Paint.Style.STROKE);
        mArcBackPaint.setStrokeWidth(mArcWidth);
        mArcBackPaint.setColor(Color.LTGRAY);
        mArcForePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mArcForePaint.setStyle(Paint.Style.STROKE);
        mArcForePaint.setStrokeWidth(mArcWidth);
        mArcForePaint.setStrokeCap(Paint.Cap.ROUND);
        mArcRectF = new RectF();

        mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mLinePaint.setStyle(Paint.Style.STROKE);
        mLinePaint.setColor(Color.WHITE);
        mLinePaint.setStrokeWidth(DensityUtils.dp2px(context, 2));

        mProgressTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mProgressTextPaint.setStyle(Paint.Style.FILL);
        mProgressTextPaint.setColor(mTextColor);
        mProgressTextPaint.setTextSize(mProgressTextSize);

        mLabelTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mLabelTextPaint.setStyle(Paint.Style.FILL);
        mLabelTextPaint.setColor(mTextColor);
        mLabelTextPaint.setTextSize(mLabelTextSize);

        mTextRect = new Rect();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measuredDimension(widthMeasureSpec), measuredDimension(heightMeasureSpec));
    }

    private int measuredDimension(int measureSpec) {
        int result;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            result = 800;
            if (mode == MeasureSpec.AT_MOST) {
                result = Math.min(result, size);
            }
        }
        return result;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mArcRectF.set(mArcWidth / 2, mArcWidth / 2, getWidth() - mArcWidth / 2, getHeight() - mArcWidth / 2);
        //画背景弧线
        canvas.drawArc(mArcRectF, -90, 360, false, mArcBackPaint);
        //设置渐变渲染
        LinearGradient linearGradient = new LinearGradient(getWidth() / 2, 0, getWidth() / 2, getHeight(), mColorArray, null, Shader.TileMode.CLAMP);
        mArcForePaint.setShader(linearGradient);
        //画百分比值弧线
        canvas.drawArc(mArcRectF, -90, mSweepAngle, false, mArcForePaint);
        //画百分比文本
        String progressText = mProgress + "%";
        mProgressTextPaint.getTextBounds(progressText, 0, progressText.length(), mTextRect);
        float progressTextWidth = mTextRect.width();
        float progressTextHeight = mTextRect.height();
        canvas.drawText(progressText, getWidth() / 2 - progressTextWidth / 2,
                getHeight() / 2 + progressTextHeight / 2, mProgressTextPaint);
        //画标签说明文本
        mLabelTextPaint.getTextBounds(mLabelText, 0, mLabelText.length(), mTextRect);
        canvas.drawText(mLabelText, getWidth() / 2 - mTextRect.width() / 2,
                getHeight() / 2 - progressTextHeight / 2 - mTextRect.height(), mLabelTextPaint);
    }

    public void setProgress(float progress) {
        ValueAnimator anim = ValueAnimator.ofFloat(mProgress, progress);
        anim.setDuration((long) (Math.abs(mProgress - progress) * 20));
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mProgress = (float) animation.getAnimatedValue();
                mSweepAngle = mProgress * 360 / 100;
                mProgress = (float) (Math.round(mProgress * 10)) / 10;//四舍五入保留到小数点后两位
                invalidate();
            }
        });
        anim.start();
    }

}

地址:

csdn:http://download.csdn.net/download/qq_38367802/10172775
github:https://github.com/liuzhenhang/myview

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值