自定义View(二)圆形进度条

作者: 请你吃鱼 | 来源:发表于2016-08-17 15:31 被阅读333次

在实际开发中,有时候会用到圆形的进度条来显示所占的百分比或者进度,但是Android原生SDK中并没有提供这样的控件,这就需要我们自定义了。
首先,我们分析一下自定义这样一个控件都需要用到哪些属性,长宽自然就不必说了,还有进度、线条的宽度、颜色等等。我们现在values文件夹中创建attrs.xml文件,下面是所需要的属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="color" format="color"/>
    <attr name="lineWidth" format="dimension"/>
    <attr name="progress" format="integer"/>
    <attr name="duration" format="integer"/>
    <attr name="useAnim" format="boolean"/>

    <declare-styleable name="CircleProgressBar">
        <attr name="color"/>
        <attr name="lineWidth"/>
        <attr name="progress"/>
        <attr name="duration"/>
        <attr name="useAnim"/>
    </declare-styleable>
</resources>

我们可以看到这里有我们需要的几个属性,duration和useAnim的作用我们稍后再讲。创建CircleProgressBar类继承View,并创建构造函数,然后获取控件的属性。

    private Paint paint;
    private int color;
    private int lineWidth;
    private int progress;
    private int duration;
    private boolean useAnim;

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

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

    public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar, defStyleAttr, 0);
        color = array.getColor(R.styleable.CircleProgressBar_color, Color.BLACK);
        lineWidth = array.getDimensionPixelOffset(R.styleable.CircleProgressBar_lineWidth, 0);
        progress = array.getInt(R.styleable.CircleProgressBar_progress, 30);
        duration = array.getInt(R.styleable.CircleProgressBar_duration, 2000);
        useAnim = array.getBoolean(R.styleable.CircleProgressBar_useAnim, true);
        array.recycle();
        paint = new Paint();
    }

先抛出几个异常:

 private void throwException() {
        if (getWidth() != getHeight()) {
            throw new RuntimeException("width and height must be equal");
        }
        if (progress > 100) {
            throw new RuntimeException("progress can't be bigger than hundred");
        }
        if (progress < 0) {
            throw new RuntimeException("progress can't be smaller than zero");
        }
    }

可以看到,如果控件的宽高不相等就会抛出一个异常,这也是为了节省一下时间。然后重写onDraw方法,调用throwException。

 @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        throwException();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(lineWidth);
        paint.setColor(Color.parseColor("#e9e9e9"));
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2 - lineWidth / 2, paint);
        paint.setColor(color);
        RectF oval = new RectF(lineWidth / 2, lineWidth / 2, getWidth() - lineWidth / 2, getHeight() - lineWidth / 2);
        canvas.drawArc(oval, -90, progress * 360 / 100, false, paint);
    }

我们先来分析一下上面的代码,先设置画笔的颜色,然后画一个圆,这里的圆是作为进度条的背景颜色用的,drawCircle中的参数分别是圆心的坐标,圆的半径还有画笔,这里需要注意的一点是由于进度条的线条是有宽度的,所以圆的半径并不是简单的用控件的宽度除以2,而是圆心到线条中间一点的位置,所以是控件宽度的一半减去线条宽度的一半。然后画弧度,这里弧线所在矩形的四条边的位置原理和画圆的一样。
我们在布局文件中使用一下,可以看到刚才自定义的属性全部都可以提示出来。



设置颜色和宽度,运行一下就是这个样子了:



那前面的duration和useAnim属性是做什么的呢,我们经常看到有些进度条设置时是有动画的,前面这两个属性就是做这个的,我们来看一下绘制进度的这句代码
canvas.drawArc(oval, -90, progress * 360 / 100, false, paint);

这里我们是用当前进度去设置所画进度的角度,如果我们需要在设置进度时有一个动画过程,那这个progress是一个渐变的,所以我们需要用到属性动画,顾名思义,我们用这个动画是不断改变控件的属性的,所以我么需要在设置进度将progress从0到某个进度进行变化:

public void setProgress(int p) {
        if (useAnim)
            startAnim(p);
        else
            invalidate();
    }

    private void startAnim(int p) {
        ValueAnimator animator = ValueAnimator.ofInt(0, p);
        animator.setDuration(duration);
        animator.start();
        animator.addUpdateListener(valueAnimator -> {
            progress = (int) valueAnimator.getAnimatedValue();
            invalidate();
        });
    }

这里我们用到了ValueAnimator,在动画监听中将progress从设置的区间中取出,然后刷新,这样就形成了一个动画的效果。


相关文章

  • Android-自定义进度条

    ProgressBar 参考文章:Android 高手进阶之自定义View,自定义属性(带进度的圆形进度条)and...

  • iOS 制作个圆形进度条

    1.需要做个这样的圆形进度条 自定义弹窗view就不说了,主要是这个圆形进度view,底色是灰色然后有进度灰色被...

  • Android 自定义圆形进度条

    Android简易的圆形进度条 自定义View基础入门看2个系列文章,非常优秀的文章。安卓自定义View教程目录H...

  • Android常用控件之ProgressBar,圆形进度条

    目录:android.widget.ProgressBar 前言:中间带百分比的圆形进度条xml布局 自定义view:

  • Android圆形进度条自定义

    自定义圆形进度条 实现 圆形进度条api 使用 将MyCircleProgressView和attrs.xml下的...

  • android 圆形进度条

    圆形的进度条,自定义控件实现

  • 自定义View(二)圆形进度条

    在实际开发中,有时候会用到圆形的进度条来显示所占的百分比或者进度,但是Android原生SDK中并没有提供这样的控...

  • 自定义View实战四:圆形进度条

    本文介绍自定义圆形进度条的实现,主要利用自定义 View 和动画相关知识。 下面是效果图 实现步骤分析准备好外层圆...

  • ProgressBar

    普通进度条 样式 圆形和水平【默认圆形】 自定义水平进度条 在这个Style中,有一个progressDrawab...

  • 自定义View 圆形进度条

    目录 效果 按照惯例,放上效果图 前言 上一篇 文章把断点续传的功能分享了一下,有兴趣的朋友可以看一看。接下来就给...

网友评论

本文标题:自定义View(二)圆形进度条

本文链接:https://www.haomeiwen.com/subject/ktumsttx.html