自定义进度条及仿58数据加载效果

在项目开发中都会涉及到网络加载,文件上传或者下载,都会用到显示当前加载进度的进度条效果,最近刚好学了下自定义进度条,效果如下:

device-2017-06-28-115744.gif

上面效果的实现还是通过自定义view,通过onMeasure()方法测量,onDraw()方法绘制实现的,一共涉及到三个东西的绘制,内圆(蓝色圆)、外圆(黄色圆)、中间文字的绘制,绘制完这些就可以实现大致效果了;不过还是跟之前几篇自定view播客一样,在绘制之前需要初始化自定义属性和画笔;
初始化定义属性:

       //初始化属性
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ProgressBar);
        mInnerBackground = array.getColor(R.styleable.ProgressBar_innerBackground, mInnerBackground);
        mOutterBackground = array.getColor(R.styleable.ProgressBar_outterBackground, mOutterBackground);
        mProgressTextColor = array.getColor(R.styleable.ProgressBar_progressTextColor, mProgressTextColor);

        mProgressTextSize = array.getDimensionPixelSize(R.styleable.ProgressBar_progressTextSize, sp2px(mProgressTextSize));
        mRoundWidth = (int) array.getDimension(R.styleable.ProgressBar_roundWidth, dip2px(mRoundWidth));
        array.recycle();

初始化画笔:

    /**
     * 根据绘制的颜色获取画笔
     * @param color
     */
    private Paint getPaint(int color){
        Paint paint=new Paint();
        paint.setAntiAlias(true);
        paint.setColor(color);
        paint.setStrokeWidth(mRoundWidth);
        paint.setStyle(Paint.Style.STROKE);
        return paint;
    }

初始化完成后,就在onMeasure()方法中进行测量;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        //宽高不一致时区最小值
        width = Math.min(width, height);
        height = Math.min(width, height);
        setMeasuredDimension(width, height);
    }

为了保证宽高一致使用Math.min(width, height)方法取最小值,这里直接用三元运算符也可以,其实Math.min(width, height)方法也是用的是三元运算符进行计算的;
Math.min(width, height)方法源码:

  * @param   a   an argument.
     * @param   b   another argument.
     * @return  the smaller of {@code a} and {@code b}.
     */
    public static int min(int a, int b) {
        return (a <= b) ? a : b;
    }

接下来进行绘制:

   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int center = getWidth() / 2;
        //先绘制内圆
        canvas.drawCircle(center, center, center - mRoundWidth / 2, mInnerPaint);

        //绘制外圆 画圆弧
        if (mMax == 0) {
            return;
        }
        RectF rectf = new RectF(0 + mRoundWidth / 2, 0 + mRoundWidth / 2, getWidth() - mRoundWidth / 2, getHeight() - mRoundWidth / 2);
        float preProgree = (float) mCurrentProgress / mMax;
        canvas.drawArc(rectf, 0, preProgree * 360, false, mOutterPaint);

        //绘制进度文字
        String text = ((int)(preProgree * 100)) + "%";
        Rect rect = new Rect();
        textPaint.getTextBounds(text, 0, text.length(), rect);

        int x = getWidth() / 2 - rect.width() / 2;
        Paint.FontMetricsInt metricsInt = textPaint.getFontMetricsInt();
        int dy = (metricsInt.bottom - metricsInt.top) / 2 - metricsInt.bottom;
        int baseLine = getHeight() / 2 + dy;
        canvas.drawText(text, x, baseLine, textPaint);
    }

绘制外圆的时候需要注意,外圆调用的不是canvas.drawCircle()方法,而是调用canvas.drawArc()绘制圆弧的方法进行绘制,这样效果就绘制完成了;接着又简单实现了下仿58的一个数据加载的效果;

device-2017-06-28-120345.gif

这里就只实现了圆,正方形,正三角的一个切换效果,这个效果也是采用绘制实现的;在绘制的时候要定义一个变量用来表明当前绘制的是哪个图形;

    public enum Shape {
        Circle, Square, Triangle
    }

这里用枚举来控制当前应该绘制哪个图形;同时在绘制完一个图形后还要改变当前的这个状态值;比如,绘制完圆,就要将状态改成正方形,绘制完正方形,就要将状态改成正三角,一直这样循环的去绘制;

     /**
     * 改变当前绘制的状态
     */
    public void exchange() {
        switch (mCurrentShape) {
            case Circle:
                mCurrentShape = Shape.Square;
                break;
            case Square:
                mCurrentShape = Shape.Triangle;
                break;
            case Triangle:
                mCurrentShape = Shape.Circle;
                break;
        }
        //进行绘制
        invalidate();
    }

调用invalidate();最终就会去调用onDraw();方法进行绘制;

   @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        switch (mCurrentShape) {
            case Circle:
                //画圆形
                int center = getWidth() / 2;
                mPaint.setColor(mCircleColor);
                canvas.drawCircle(center, center, center, mPaint);
                break;
            case Square:
                //画正方形
                mPaint.setColor(mSquareColor);
                canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
                break;
            case Triangle:
                //画三角形  绘制路线
                mPaint.setColor(mTriangleColor);
                if (mPath == null) {
                    mPath = new Path();
                    mPath.moveTo(getWidth() / 2, 0);
                    mPath.lineTo(0, (float) (getWidth() / 2 * Math.sqrt(3)));
                    mPath.lineTo(getWidth(), (float) (getWidth() / 2 * Math.sqrt(3)));
//                    path.lineTo(getWidth()/2,0);
                    //将绘制的路径闭合
                    mPath.close();
                }
                canvas.drawPath(mPath, mPaint);

                break;
        }
    }

绘制圆或者正方形的时候调用相应的方法就可以进行绘制了,对于三角形的绘制并没有提供相应的方法,就要采用绘制路线的方式进行绘制,

QQ截图20170628163950.jpg

从A点绘制到B点,从B点绘制到C点,从C点绘制到A点就可以了;从C点绘制到A点的时候,不采用这种方式也可以,从B点绘制到C点后直接调用mPath.close();方法将绘制路线闭合就可以了;因为要绘制的是等边三角形,在绘制的时候就要注意高度并不是getHeight();了,这里就要用到正弦这些东西来计算了,绘制的宽度是知道的,还是getWidth(),角度也知道,计算出高度就可以绘制了,绘制完成后,运行下就可以了。
源码地址:http://pan.baidu.com/s/1i587fnv

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,194评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,058评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,780评论 0 346
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,388评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,430评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,764评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,907评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,679评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,122评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,459评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,605评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,270评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,867评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,734评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,961评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,297评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,472评论 2 348

推荐阅读更多精彩内容