美文网首页Android技术知识Android开发Android自定义View
Android自定义View之手把手带你自定义一个进度条

Android自定义View之手把手带你自定义一个进度条

作者: AntDream | 来源:发表于2018-09-23 14:49 被阅读17次

    本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点

    自定义View是平时开发过程中逃不过的一劫,效果千变万化,唯有迎难而上,才能以不变应万变。

    进度条效果示意图

    分析需求

    这次碰到一个简单的需求,就是如上图的加载进度条。分析总结后就几条:

    • 初始时是一圈虚线
    • 进度开始时慢慢绘制实线
    • 加载成功时加快实线的绘制,快速绘制完一圈表示成功

    分析完需求,那我们就来想想怎么实现这个特殊的View。

    准备工作

    首先我们肯定先需要掌握基本的View的绘制,比如画笔Paint、画布Canvas,以及View的绘制原理等。

    自定义View,其实可以这样简单来理解:假设我们自己拿笔去画这个图,我们会怎么画?会有哪些步骤?然后我们用学到的知识编写程序让计算机帮我们画。所以我们得先自己知道怎么去画才行。

    这里我分析一下,可分为这几步:

    1. 先画一圈虚线
    2. 然后根据进度绘制实线
    3. 当收到加快进度的信号后快速绘制完一圈实线

    这里就有几个点了:

    1. 怎么快速绘制出一圈虚线呢?
    2. 绘制实线怎么控制绘制的快慢呢?
    3. 怎么加快实线的绘制呢?

    预备知识:

    实践

    这里我们采用继承View的方式来实现

    画虚线

    这里最简单的方式就是利用Paint的PathEffect属性,PathEffect属性用来控制画笔Paint的路径样式,比如虚线,折线的拐角圆滑等。

    虚线对应的PathEffect为DashPathEffect,具体用法如下:

    mRimPaint.setPathEffect(new DashPathEffect(new float[]{3f, 30f}, 0));
    

    其中float数组用来控制虚线的效果,数组的第一个元素控制虚线的长短,第二个用来控制虚线之间的间隔,具体的效果大家可以动手试一下,这样子比较直观。需要注意的是float数组里面必须至少包含2个元素,并且必须是偶数个元素。

    所以我们画一圈虚线就简单了:

    //虚线画笔
    mRimPaint = new Paint();
    mRimPaint.setAntiAlias(true);
    mRimPaint.setStyle(Paint.Style.STROKE);
    mRimPaint.setColor(this.mRimColor);
    mRimPaint.setStrokeWidth(this.mRimWidth);
    mRimPaint.setStrokeCap(Paint.Cap.ROUND);
    mRimPaint.setPathEffect(new DashPathEffect(new float[]{3f, 30f}, 0));
    

    其中需要注意的是,setStrokeCap这个属性。我们设置的 Cap.ROUND 属性能让我们绘制出的线段更加圆滑。其他的属性在预备知识中都有介绍。

    准备好画笔以后我们就可以开始绘制我们的虚线了,绘制当然需要在onDraw方法中

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawArc(mCircleBounds, 360.0f, 360.0f, false, mRimPaint);
    }
    

    这里我们采用了Canvas的drawArc方法,就是绘制一段360度的圆弧。具体的参数属性可以参看上面预备知识中关于Canvas的文章。

    其中需要注意的是第一个参数,也就是圆弧外框矩形的确定。这个矩形的作用就是确定整个图形的边界,因为我们的线段是有宽度的,所以在计算边界的时候需要考虑到线段的宽度。

    实际上我们后面肯定要让这个进度条的一些属性能自定义,比如进度条的颜色,宽度等,所以我们在绘制的时候就需要考虑到进度条宽度的问题。

    要解决这个问题也简单,在创建这个外框时,把进度条的宽度考虑进去就行了。具体看代码:

    float circleWidthHalf = (float) this.mBarWidth / 2.0F > (float) this.mRimWidth / 2.0F ? (float) this.mBarWidth / 2.0F : (float) this.mRimWidth / 2.0F;
    this.mCircleBounds = new RectF(paddingLeft + circleWidthHalf, paddingTop + circleWidthHalf, (float) width - paddingRight - circleWidthHalf, (float) height - paddingBottom - circleWidthHalf);
    
    

    其中,mBarWidth是实线进度条的宽度,mRimWidth是虚线的宽度。由于实线和虚线可能宽度不一样,所以我们需要以较宽的为准。

    画实线进度条

    有了以上的基础,那画实线进度条就简单了。同样是先设置Paint,然后用drawArc方法绘制。

    设置Paint属性

    //实线画笔
    mBarPaint = new Paint();
    mBarPaint.setAntiAlias(true);
    mBarPaint.setColor(this.mBarColor);
    mBarPaint.setStyle(Paint.Style.STROKE);
    mBarPaint.setStrokeCap(Paint.Cap.ROUND);
    mBarPaint.setStrokeWidth(this.mBarWidth);
    

    然后用Canvas的drawArc方法绘制

    canvas.drawArc(this.mCircleBounds, (float) this.mStartAngle, degrees, false, this.mBarPaint);
    

    这里绘制实线就需要特殊处理了,因为我们需要慢慢地绘制,而不是一次性的绘制出一个实线圆。这里的思路也很简单,就是随着时间的推移慢慢地绘制实线进度,只不过角度越来越大。

    所以要有加载的进度效果,关键就是要控制绘制实线的角度了,那这个角度怎么确定呢?我们又怎么在角度改变时,实时刷新我们的View呢?

    我们下次见分晓......


                           欢迎关注我的微信公众号,和我一起每天进步一点点!
    
    AntDream

    相关文章

      网友评论

        本文标题:Android自定义View之手把手带你自定义一个进度条

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