自定义view之圆形进度条初体验

自定义圆形进度条是一个很简单的项目,开发起来没什么难度,但非常适合练手,现在说一下开发思路吧!

实现效果:

这里写图片描述

实现思路:

1,画出默认圆环
2,在默认圆环基础上画进度圆环
3,在中心画文字

实现步骤:

在values下创建attrs文件,并自定义属性,分析属性有:默认圆环颜色,进度圆环颜色,圆半径,圆环宽度,字体大小等

  <!--自定义圆形进度条-->
    <declare-styleable name="CustomProgress">
        <attr name="radius" format="dimension" /><!--半径-->
        <attr name="strokeWidth" format="dimension" /><!--画笔宽度-->
        <attr name="defaultColor" format="color" /><!--默认环形颜色-->
        <attr name="progressColor" format="color" /><!--进度条颜色-->
        <attr name="totalProgress" format="integer" /><!--总进度-->
        <attr name="textColor" format="color|reference" /><!--字体颜色-->
        <attr name="mTextSize" format="dimension"/><!--字体大小-->
    </declare-styleable>

然后获取属性

    public ArcView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray array=context.getTheme().obtainStyledAttributes(attrs,R.styleable.CustomProgress,0,0);
        try {
            radius=array.getDimension(R.styleable.CustomProgress_radius,200);
            strokeWidth=array.getDimension(R.styleable.CustomProgress_strokeWidth,40);
            totalProgress=array.getInt(R.styleable.CustomProgress_totalProgress,100);
            defaultColor=array.getColor(R.styleable.CustomProgress_defaultColor,Color.GREEN);
            progressColor=array.getColor(R.styleable.CustomProgress_totalProgress,Color.RED);
            textColor=array.getColor(R.styleable.CustomProgress_textColor,Color.BLACK);
            mTextSize=array.getDimensionPixelSize(R.styleable.CustomProgress_mTextSize,28);
        } finally {
            array.recycle();
        }

        init();

    }

    private void init() {
        mPaint=new Paint();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);//抗锯齿
        mPaint.setDither(true);//防抖动
    }

重写ondraw方法

  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(textColor);
        mPaint.setTextSize(mTextSize);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        String text = "";
        if (mProgress == totalProgress) {
            text = "下载成功!";
        } else {
            text = (int) (((float) mProgress / (float) totalProgress) * 100) + "%";
        }

        float textWidth = mPaint.measureText(text, 0, text.length());
        canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2 + mTextSize / 2, mPaint);
        mPaint.setColor(defaultColor);
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        RectF rectfs = new RectF();
        rectfs.top = getHeight() / 2 - radius;
        rectfs.bottom = getHeight() / 2 + radius;
        rectfs.left = getWidth() / 2 - radius;
        rectfs.right = getWidth() / 2 + radius;
        canvas.drawArc(rectfs, 0, 360, false, mPaint);
        mPaint.setColor(progressColor);
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        RectF rectf = new RectF();
        rectf.top = getHeight() / 2 - radius;
        rectf.bottom = getHeight() / 2 + radius;
        rectf.left = getWidth() / 2 - radius;
        rectf.right = getWidth() / 2 + radius;
        canvas.drawArc(rectf, 0, mProgress * 360 / totalProgress, false, mPaint);

    }

刷新进度,在主页面设置进度,因为是耗时操作,故要开启线程

 final ArcView view= (ArcView) findViewById(R.id.arcview);
        new Thread(new Runnable() {
            @Override
            public void run() {
               while (progress<=100){
                   progress+=3;
                   view.setProgress(progress);
                   try {
                       Thread.sleep(100);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
            }
        }).start();

设置进度

 /**
     * 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步
     * 刷新界面调用postInvalidate()能在非UI线程刷新
     * @param progress
     */
    public synchronized void setProgress(int progress) {
        if(progress < 0){
            throw new IllegalArgumentException("progress not less than 0");
        }
        if(progress > totalProgress){
            progress = totalProgress;
        }
        if(progress <= totalProgress){
            this.mProgress = progress;
            postInvalidate();
        }

    }

效果:
这里写图片描述

改变一下ondraw()。换种风格

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.CYAN);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(getWidth()/2,getHeight()/2,radius,mPaint);
        mPaint.setColor(textColor);
        mPaint.setTextSize(mTextSize);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        String text = "";
        if (mProgress == totalProgress) {
            text = "下载成功!";
        } else {
            text = (int) (((float) mProgress / (float) totalProgress) * 100) + "%";
        }

        float textWidth = mPaint.measureText(text, 0, text.length());
        canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2 + mTextSize / 2, mPaint);
        mPaint.setColor(defaultColor);
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        RectF rectfs = new RectF();
        rectfs.top = getHeight() / 2 - radius;
        rectfs.bottom = getHeight() / 2 + radius;
        rectfs.left = getWidth() / 2 - radius;
        rectfs.right = getWidth() / 2 + radius;
        canvas.drawArc(rectfs, 0, 360, false, mPaint);
        mPaint.setColor(progressColor);
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        RectF rectf = new RectF();
        rectf.top = getHeight() / 2 - radius;
        rectf.bottom = getHeight() / 2 + radius;
        rectf.left = getWidth() / 2 - radius;
        rectf.right = getWidth() / 2 + radius;
        canvas.drawArc(rectf, 0, mProgress * 360 / totalProgress, false, mPaint);

    }

效果:

这里写图片描述

注释掉默认圆环效果

   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setColor(Color.CYAN);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(getWidth()/2,getHeight()/2,radius,mPaint);
        mPaint.setColor(textColor);
        mPaint.setTextSize(mTextSize);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        String text = "";
        if (mProgress == totalProgress) {
            text = "下载成功!";
        } else {
            text = (int) (((float) mProgress / (float) totalProgress) * 100) + "%";
        }

        float textWidth = mPaint.measureText(text, 0, text.length());
        canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2 + mTextSize / 2, mPaint);
//        mPaint.setColor(defaultColor);
//        mPaint.setStrokeWidth(strokeWidth);
//        mPaint.setStyle(Paint.Style.STROKE);
//        RectF rectfs = new RectF();
//        rectfs.top = getHeight() / 2 - radius;
//        rectfs.bottom = getHeight() / 2 + radius;
//        rectfs.left = getWidth() / 2 - radius;
//        rectfs.right = getWidth() / 2 + radius;
//        canvas.drawArc(rectfs, 0, 360, false, mPaint);
        mPaint.setColor(progressColor);
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        RectF rectf = new RectF();
        rectf.top = getHeight() / 2 - radius;
        rectf.bottom = getHeight() / 2 + radius;
        rectf.left = getWidth() / 2 - radius;
        rectf.right = getWidth() / 2 + radius;
        canvas.drawArc(rectf, 0, mProgress * 360 / totalProgress, false, mPaint);

    }

效果:
这里写图片描述

也可以让圆环在内圆外侧,将圆形半径减去圆环宽度的一半即可,看效果。

这里写图片描述

实心圆进度条:

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        mPaint.setColor(Color.CYAN);
//        mPaint.setStyle(Paint.Style.FILL);
//        canvas.drawCircle(getWidth()/2,getHeight()/2,radius-strokeWidth/2,mPaint);

        mPaint.setColor(defaultColor);
        mPaint.setStrokeWidth(2);
        mPaint.setStyle(Paint.Style.STROKE);
        RectF rectfs = new RectF();
        rectfs.top = getHeight() / 2 - radius;
        rectfs.bottom = getHeight() / 2 + radius;
        rectfs.left = getWidth() / 2 - radius;
        rectfs.right = getWidth() / 2 + radius;
        canvas.drawArc(rectfs, 0, 360, false, mPaint);
        mPaint.setColor(progressColor);
//        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        RectF rectf = new RectF();
        rectf.top = getHeight() / 2 - radius;
        rectf.bottom = getHeight() / 2 + radius;
        rectf.left = getWidth() / 2 - radius;
        rectf.right = getWidth() / 2 + radius;
        canvas.drawArc(rectf, 0, mProgress * 360 / totalProgress, true, mPaint);
        mPaint.setColor(textColor);
        mPaint.setTextSize(mTextSize);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(2);
        String text = "";
        if (mProgress == totalProgress) {
            text = "下载成功!";
        } else {
            text = (int) (((float) mProgress / (float) totalProgress) * 100) + "%";
        }

        float textWidth = mPaint.measureText(text, 0, text.length());
        canvas.drawText(text, getWidth() / 2 - textWidth / 2, getHeight() / 2 + mTextSize / 2, mPaint);
    }

效果:

这里写图片描述

基础知识可以参考:
https://github.com/GcsSloop/AndroidNote

源码下载地址:
http://download.csdn.net/detail/qq_16131393/9622840

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值