Android 自定义圆弧进度条加数字动态变化的实现

效果如下:
在这里插入图片描述
思路:一个内环圆弧和一个外环圆弧,因为有一个圆圈是在圆弧上做圆周运动,所以在画圆的时候必须要得到圆弧上的各个点的坐标,这里其实就用到了PathMeasure这个类,可以帮我们拿到这些点,在画圆弧的时候也理所应当的要使用path,然后根据外界动态的传值进行重绘就能达到动态的效果

代码如下:

public class ProgressPathRainbow extends View {
    private Paint outPaint;
    private Paint innerPaint;
    private Paint mTextPaint;
    private Paint mRmbTextPaint;
    private int mBorderWidth = 40;
    private int mCircleRadius = 40;
    private int mCurrentProgress = 0;
    private int mMaxProgress = 0;
    private int startAngle = 180;

    private int sweepAngels = 180;
    private Paint mCirclePaint;
    private String rmb = "¥";
    private String currentText = "0.0";

    public void setCurrentText(String currentText) {
        this.currentText = currentText;
    }

    //储存位置点
    private float[] pos =new float[2];

    public ProgressPathRainbow(Context context) {
        super(context);
        initPaint();
    }

    public ProgressPathRainbow(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initPaint();
    }

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

    private void initPaint(){
        outPaint = new Paint();
        outPaint.setColor(0xFFECECEC);
        outPaint.setAntiAlias(true);
        outPaint.setStyle(Paint.Style.STROKE);
        outPaint.setStrokeCap(Paint.Cap.ROUND);
        outPaint.setStrokeWidth(mBorderWidth);

        //
        innerPaint = new Paint();
        innerPaint.setColor(0xffFBA123);
        innerPaint.setAntiAlias(true);
        innerPaint.setStyle(Paint.Style.STROKE);
        innerPaint.setStrokeCap(Paint.Cap.ROUND);
        innerPaint.setStrokeWidth(mBorderWidth);

        mCirclePaint = new Paint();
        mCirclePaint.setColor(Color.WHITE);
        mCirclePaint.setStyle(Paint.Style.FILL);

        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(0xffE5423D);
        mTextPaint.setFakeBoldText(true);
        mTextPaint.setTextSize(SizeUtils.sp2px(42));


        mRmbTextPaint = new Paint();
        mRmbTextPaint.setAntiAlias(true);
        mRmbTextPaint.setColor(0xffE5423D);
        mRmbTextPaint.setTextSize(SizeUtils.sp2px(18));

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        if (width >= height){
            setMeasuredDimension(height,height);
        }else {
            setMeasuredDimension(width,width);
        }


    }

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

        RectF rectF = new RectF(mBorderWidth,mBorderWidth,getWidth()-mBorderWidth,getHeight()-mBorderWidth);
        //画内环圆弧
        Path outerPath = new Path();
        outerPath.arcTo(rectF,startAngle,sweepAngels);
        canvas.drawPath(outerPath,outPaint);
        //画外环圆弧
        Path innerPah = new Path();
        float percent = (float)mCurrentProgress/mMaxProgress;
        innerPah.arcTo(rectF,startAngle,percent*sweepAngels);
        canvas.drawPath(innerPah,innerPaint);



        //画金额
        String tempText = new BigDecimal(currentText).multiply(new BigDecimal(percent)).setScale(1, RoundingMode.HALF_UP).toString();
        Rect textBounds = new Rect();
        mTextPaint.getTextBounds(tempText, 0, tempText.length(), textBounds);
        int dx = getWidth()/2 - textBounds.width()/2;
        // 基线 baseLine
        Paint.FontMetricsInt  fontMetrics = mTextPaint.getFontMetricsInt();
        int dy = (fontMetrics.bottom - fontMetrics.top)/2 - fontMetrics.bottom;
        int baseLine = getHeight()/3 + dy;
        canvas.drawText(tempText,dx,baseLine,mTextPaint);

        //画人民币符号

        Rect textBoundRmbs = new Rect();
        mTextPaint.getTextBounds(rmb, 0, rmb.length(), textBoundRmbs);
        int dxRmb = dx-50;
        // 基线 baseLine
        Paint.FontMetricsInt  fontMetricsRmb = mTextPaint.getFontMetricsInt();
        int dyRmb = (fontMetricsRmb.bottom - fontMetricsRmb.top)/2 - fontMetricsRmb.bottom;
        int baseLineRmb = getHeight()/3 + dyRmb;
        canvas.drawText(rmb,dxRmb,baseLineRmb,mRmbTextPaint);

        //获取圆弧上点的位置(坐标,画一个圆)
        PathMeasure pathMeasure = new PathMeasure(outerPath,false);
        boolean posTan = pathMeasure.getPosTan(pathMeasure.getLength() * percent, pos, null);
        canvas.drawCircle(pos[0],pos[1],mCircleRadius,mCirclePaint);

    }

    public synchronized void setmCurrentProgress(int mCurrentProgress) {
        this.mCurrentProgress = mCurrentProgress;
        invalidate();
    }

    public synchronized void setmMaxProgress(int mMaxProgress) {
        this.mMaxProgress = mMaxProgress;
    }
}

以上就可以实现这个效果
使用的话可以这样

 detailRainbowPr.setmMaxProgress(100);
	detailRainbowPr.setCurrentText("99.9");
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0, 100);
        valueAnimator.setDuration(5000);
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.addUpdateListener(valueAnimator1 -> {
            float step = (float) valueAnimator1.getAnimatedValue();
            detailRainbowPr.setmCurrentProgress((int) step);
        });
        valueAnimator.start();
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值