安卓自定义圆形带百分比进度条组件

java 复制代码
public class CirclePercentBar extends View {

    private Context mContext;

    private int mArcColor;
    private int mArcWidth;
    private int mCenterTextColor;
    private int mCenterTextSize;
    private int mCircleRadius;
    private Paint arcPaint;
    private Paint arcCirclePaint;
    private Paint centerTextPaint;
    private RectF arcRectF;
    private Rect textBoundRect;
    private float mCurData = 0;
    private String mSuffix = "%";
    private int arcStartColor;
    private int arcEndColor;
    private Paint startCirclePaint;

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

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

    public CirclePercentBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CirclePercentBar, defStyleAttr, 0);
        mArcColor = typedArray.getColor(R.styleable.CirclePercentBar_arcColor, 0xff0000);
        mArcWidth = typedArray.getDimensionPixelSize(R.styleable.CirclePercentBar_arcWidth, DisplayUtil.dp2px(context, 20));
        mCenterTextColor = typedArray.getColor(R.styleable.CirclePercentBar_centerTextColor, 0x0000ff);
        mCenterTextSize = typedArray.getDimensionPixelSize(R.styleable.CirclePercentBar_centerTextSize, DisplayUtil.dp2px(context, 20));
        mCircleRadius = typedArray.getDimensionPixelSize(R.styleable.CirclePercentBar_circleRadius, DisplayUtil.dp2px(context, 100));
        arcStartColor = typedArray.getColor(R.styleable.CirclePercentBar_arcStartColor,
                ContextCompat.getColor(mContext, R.color.colorStart));
        arcEndColor = typedArray.getColor(R.styleable.CirclePercentBar_arcEndColor,
                ContextCompat.getColor(mContext, R.color.colorEnd));

        typedArray.recycle();

        initPaint();

    }

    private void initPaint() {

        startCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        startCirclePaint.setStyle(Paint.Style.FILL);
        startCirclePaint.setColor(arcStartColor);

        arcCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        arcCirclePaint.setStyle(Paint.Style.STROKE);
        arcCirclePaint.setStrokeWidth(mArcWidth);
        arcCirclePaint.setColor(ContextCompat.getColor(mContext, R.color.colorCirclebg));
        arcCirclePaint.setStrokeCap(Paint.Cap.ROUND);

        arcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        arcPaint.setStyle(Paint.Style.STROKE);
        arcPaint.setStrokeWidth(mArcWidth);
        arcPaint.setColor(mArcColor);
        arcPaint.setStrokeCap(Paint.Cap.ROUND);

        centerTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        centerTextPaint.setStyle(Paint.Style.FILL);
        centerTextPaint.setColor(Color.BLACK);
        centerTextPaint.setTextSize(mCenterTextSize);

        //圓弧的外接矩形
        arcRectF = new RectF();

        //文字的边界矩形
        textBoundRect = new Rect();

    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(measureDimension(widthMeasureSpec), measureDimension(heightMeasureSpec));
    }

    private int measureDimension(int measureSpec) {
        int result;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = mCircleRadius * 2;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    @Override
    protected void onDraw(Canvas canvas) {

        canvas.rotate(-90, getWidth() / 2, getHeight() / 2);

        arcRectF.set(getWidth() / 2 - mCircleRadius + mArcWidth / 2, getHeight() / 2 - mCircleRadius + mArcWidth / 2
                , getWidth() / 2 + mCircleRadius - mArcWidth / 2, getHeight() / 2 + mCircleRadius - mArcWidth / 2);

        canvas.drawArc(arcRectF, 0, 360, false, arcCirclePaint);

        arcPaint.setShader(new SweepGradient(getWidth() / 2, getHeight() / 2, arcStartColor, arcEndColor));
        canvas.drawArc(arcRectF, 0, 360 * mCurData / 100, false, arcPaint);

        canvas.rotate(90, getWidth() / 2, getHeight() / 2);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2 - mCircleRadius + mArcWidth / 2, mArcWidth / 2, startCirclePaint);

        String data = String.valueOf((int) mCurData) + mSuffix;
        centerTextPaint.getTextBounds(data, 0, data.length(), textBoundRect);
        canvas.drawText(data, getWidth() / 2 - textBoundRect.width() / 2, getHeight() / 2 + textBoundRect.height() / 2, centerTextPaint);

    }

    public void setPercentData(float data, final String suffix, TimeInterpolator interpolator) {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(mCurData, data);
        valueAnimator.setDuration((long) (Math.abs(mCurData - data) * 30));
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float value = (float) valueAnimator.getAnimatedValue();
                mCurData = (float) (Math.round(value * 10)) / 10;
                mSuffix = suffix;
                invalidate();
            }
        });
        valueAnimator.setInterpolator(interpolator);
        valueAnimator.start();
    }
}

调用方式

java代码里设置数值

java 复制代码
        float myFloat = completeProgress.floatValue(); // 将Double类型的值转换为float类型的值
        holder. circle_bar.setPercentData( myFloat , "%", null);
XML 复制代码
    <com.zx.mocab.views.CirclePercentBar
        android:id="@+id/circle_bar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_gravity="center_horizontal"
        app:arcColor="#0579FF"
        app:arcStartColor="#A5CFFF"
        app:arcWidth="10dp"
        app:centerTextColor="#222222"
        app:centerTextSize="24sp"
        app:circleRadius="40dp" />

效果图

相关推荐
歪楼小能手3 小时前
Android16系统go版关闭重力旋转开关后缺失手动旋转屏幕悬浮按钮
android·java·平板
崇山峻岭之间3 小时前
Matlab学习记录37
android·学习·matlab
stevenzqzq5 小时前
Android 协程 Channel 菜鸟教程
android·channel
遗悲风6 小时前
PHP伪协议全面解析:原理、常用场景、攻防实战与安全防护
android·安全·php
撩得Android一次心动6 小时前
Android Lifecycle 全面解析:掌握生命周期管理的艺术(源码篇)
android·lifecycle
stevenzqzq6 小时前
android fow 限流
android·限流·flow
冬奇Lab7 小时前
Android 15 显示子系统深度解析(二):图形缓冲区管理与HWC硬件合成
android
wings专栏7 小时前
Android触摸事件分发记录
android
aaajj7 小时前
【Android】声控拍照例子
android
stevenzqzq7 小时前
Android MVI 中 setState(reduce: State.() -> State) 设计说明文档
android·mvi框架