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

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

自定义进度条及仿58数据加载效果_第1张图片
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的一个数据加载的效果;

自定义进度条及仿58数据加载效果_第2张图片
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;
        }
    }

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

自定义进度条及仿58数据加载效果_第3张图片
QQ截图20170628163950.jpg

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

你可能感兴趣的:(自定义进度条及仿58数据加载效果)