Android 自定义View、ViewGroup 实战训练之CircleProgress

本文介绍如何在Android中自定义圆形进度条,包括属性配置、样式设置及进度更新等核心内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目中很多时候时候会用到圆形的进度条,Android系统自带的不太好看,通常我们都会去自定义它,今天我们来介绍一下自定义控件以及自定义属性的使用。

先来看一下自定义CircleProgress的代码,如果你看着太吃力,请先阅读一下Android 自定义View、ViewGroup(一)之工作原理

public class CircleProgress extends View {

    public static final int STROKE = 0;
    public static final int FILL = 1;

    private Paint paint;

    private int circleColor;
    private int progressColor;
    private int textColor;
    private float textSize;
    private float circleWidth;
    private int circleMax;
    private boolean textIsDisplay;
    private int style;

    /**
     * 当前进度
     */
    private int progress;

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

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

    public CircleProgress(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        paint = new Paint();
        TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar);
        //获取自定义属性和默认值
        circleColor = mTypedArray.getColor(R.styleable.CircleProgressBar_circle_color, Color.RED);
        progressColor = mTypedArray.getColor(R.styleable.CircleProgressBar_circle_progress_color, Color.GREEN);
        textColor = mTypedArray.getColor(R.styleable.CircleProgressBar_text_color, Color.GREEN);
        textSize = mTypedArray.getDimension(R.styleable.CircleProgressBar_text_size, 15);
        circleWidth = mTypedArray.getDimension(R.styleable.CircleProgressBar_circle_width, 5);
        circleMax = mTypedArray.getInteger(R.styleable.CircleProgressBar_circle_max, 100);
        textIsDisplay = mTypedArray.getBoolean(R.styleable.CircleProgressBar_is_text_display, true);
        style = mTypedArray.getInt(R.styleable.CircleProgressBar_style, 0);

        mTypedArray.recycle();
    }

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

        //1.画出最外层的大圆环
        int center = getWidth()/2;
        int radius = (int) (center-circleWidth/2);
        paint.setColor(circleColor); //设置圆环的颜色
        paint.setStyle(Paint.Style.STROKE); //设置空心
        paint.setStrokeWidth(circleWidth); //设置圆环的宽度
        paint.setAntiAlias(true); //消除锯齿
        canvas.drawCircle(center, center, radius, paint);

        //2.画百分比
        paint.setStrokeWidth(0);
        paint.setColor(textColor);
        paint.setTextSize(textSize);
        paint.setTypeface(Typeface.DEFAULT_BOLD);
        int percent = (int) (((float) progress / (float) circleMax) * 100);
        float textWidth = paint.measureText(percent + "%");
        if (isTextIsDisplay() && percent != 0 && style == STROKE) {
            canvas.drawText(percent + "%", center - textWidth / 2, center + textSize / 2, paint);
        }

        //3.画进度
        paint.setStrokeWidth(circleWidth);
        paint.setColor(progressColor);
        //用于定义的圆弧的形状和大小的界限
        RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius);

        switch (style) {
            case STROKE: {
                paint.setStyle(Paint.Style.STROKE);
                canvas.drawArc(oval, 0, 360 * progress / circleMax, false, paint);
                break;
            }
            case FILL: {
                paint.setStyle(Paint.Style.FILL_AND_STROKE);
                if (progress != 0)
                    canvas.drawArc(oval, 0, 360 * progress / circleMax, true, paint);
                break;
            }
        }
    }



    /**
     * 设置进度
     * @param progress
     */
    public synchronized void setProgress(int progress){
        if(progress < 0){
            throw new IllegalArgumentException("progress not less than 0");
        }
        if(progress > circleMax){
            progress = circleMax;
        }
        if(progress <= circleMax){
            this.progress = progress;
            postInvalidate();
        }
    }

    /**
     * 获取进度
     * @return
     */
    public synchronized int getProgress(){
        return progress;
    }

    public synchronized int getCircleMax() {
        return circleMax;
    }

    public synchronized void setCircleMax(int circleMax) {
        if (circleMax < 0) {
            throw new IllegalArgumentException("max not less than 0");
        }
        this.circleMax = circleMax;
    }



    public int getCircleColor() {
        return circleColor;
    }

    public void setCircleColor(int circleColor) {
        this.circleColor = circleColor;
    }

    public int getProgressColor() {
        return progressColor;
    }

    public void setProgressColor(int progressColor) {
        this.progressColor = progressColor;
    }

    public int getTextColor() {
        return textColor;
    }

    public void setTextColor(int textColor) {
        this.textColor = textColor;
    }

    public float getTextSize() {
        return textSize;
    }

    public void setTextSize(float textSize) {
        this.textSize = textSize;
    }

    public float getCircleWidth() {
        return circleWidth;
    }

    public void setCircleWidth(float circleWidth) {
        this.circleWidth = circleWidth;
    }

    public boolean isTextIsDisplay() {
        return textIsDisplay;
    }

    public void setTextIsDisplay(boolean textIsDisplay) {
        this.textIsDisplay = textIsDisplay;
    }

    public int getStyle() {
        return style;
    }

    public void setStyle(int style) {
        this.style = style;
    }
}
步骤如下:

1. 定义类继承View重写构造方法并初始化画笔Paint

2. 根据Context的obtainStyledAttributes方法获取属性集,并获取自定义属性和默认值

3. 对外暴露get、set方法,让外部可以设置和获取指定值

4.重写onDraw方法画出大圆环、百分比和进度

如果想了解更多自定义进度条,请点击

下载Demo请猛戳  AndroidStudio版

下载Demo请猛戳 Eclipse版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值