自定义控件实现带进度条的ImageView

效果如图所示:
带进度条的Imageview

代码解析:

public void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mShowProgress) {
            if (mCenterX == 0 || mCenterY == 0) {
                init();
            }
            // 画背景
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setColor(Color.parseColor("#70000000"));// 半透明
            canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
            // 画块块
            drawOval(canvas, mCenterX, mRadius);
        }
    }
  • 重写onDraw()方法,如果mShowProgress为true,则画出后面的背景以及进度条,再看init():
private void init() {
        float scale = mContext.getResources().getDisplayMetrics().density;
        mStrokeWidth = (int) (STROKE_WIDTH * scale);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);// 消除锯齿


        mCenterX = getWidth() / 2;// 圆心x
        mCenterY = getHeight() / 2;// 圆心y
    }
  • init()主要定义了进度条的宽度,初始化画笔,以及找到进度条圆心的位置。接下来在onDraw()中为Imageview盖上一层半透明的背景。接下来就是最重要的画进度条的小块了:
/**
     * 根据参数画出每个小块
     * 
     * @param canvas
     * @param centre
     * @param radius
     */
    private void drawOval(Canvas canvas, int centre, int radius) {
        int mCount;// 块块的个数
        float mSplitSize = 8 * 1.0f;// 块块空隙的宽度
        float itemSize = 8 * 1.0f;// 每个块块的宽度

        // 根据块块的大小和空隙的大小求出块块的个数
        mCount = (int) (360 * 1.0f / (mSplitSize + itemSize));
        // 求余数,将余数分配到空隙
        float yu = (360 * 1.0f % (mSplitSize + itemSize));
        mSplitSize += yu / mCount;

        RectF oval = new RectF(centre - radius, centre - radius, centre
                + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mStrokeWidth);
        mPaint.setColor(Color.parseColor("#B5B5B5")); // 设置圆环的颜色

        for (int i = 0; i < mCount; i++) {
            canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false,
                    mPaint); // 根据进度画圆弧
        }
        if (currentPosition == mCount - 1) {
            currentPosition = 0;
        }

        for (int i = 0; i < mCurrentCount; i++) {
            if (i==mCurrentCount-2) {
                mPaint.setColor(Color.parseColor("#70575757")); // 设置圆环的颜色
            }else if(i==mCurrentCount-1) {
                mPaint.setColor(Color.parseColor("#b4575757")); // 设置圆环的颜色
            }else{
                mPaint.setColor(Color.parseColor("#50575757")); // 设置圆环的颜色
            }
            canvas.drawArc(oval, (i + currentPosition)
                    * (itemSize + mSplitSize), itemSize, false, mPaint); // 根据进度画圆弧
        }
        currentPosition++;
        invalidate();
    }
  • 首先通过每一块的宽度和空隙的宽度求出小块的个数,因为小块的个数不一定被整除,我做了一个求余的操作,把多余的宽度均匀分配到各个空隙中,这样就可以保证每个块的对称性。
  • 19-29行则是画出底下固定的一圈小块,首先通过RectF 获取小块所占用的空间,再通过for循环画出一圈小块。
  • 30-45行画第二圈小块,通过currentPosition的递增不停进行移动。在35-41行通过设置颜色的不同透明度实现颜色的渐变。

    最后,给出完整的代码:

package com.linjiaxiaohai.galleryviewpager;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.widget.ImageView;

/**
 * 可显示进度的ImageView
 * 
 */
public class ProgressImageView extends ImageView {
    private Context mContext;
    public static final int STROKE_WIDTH = 5;
    private int mStrokeWidth;
    private Paint mPaint;
    private int mCenterX;
    private int mCenterY;
    private boolean mShowProgress = true;// 是否显示
    private int mRadius = 20;// 圈圈半径
    private int currentPosition = 0;// 当前开始画的位置
    private int mCurrentCount = 5;// 转圈圈的块块的个数

    public ProgressImageView(Context context) {
        super(context);
        mContext = context;
    }

    public ProgressImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    private void init() {
        float scale = mContext.getResources().getDisplayMetrics().density;
        mStrokeWidth = (int) (STROKE_WIDTH * scale);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);// 消除锯齿


        mCenterX = getWidth() / 2;// 圆心x
        mCenterY = getHeight() / 2;// 圆心y
    }

    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mShowProgress) {
            if (mCenterX == 0 || mCenterY == 0) {
                init();
            }
            // 画背景
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setColor(Color.parseColor("#70000000"));// 半透明
            canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
            // 画块块
            drawOval(canvas, mCenterX, mRadius);
        }
    }

    public void startProgress() {
        mShowProgress = true;
    }

    public void stopProgress() {
        mShowProgress = false;
    }

    /**
     * 根据参数画出每个小块
     * 
     * @param canvas
     * @param centre
     * @param radius
     */
    private void drawOval(Canvas canvas, int centre, int radius) {
        int mCount;// 块块的个数
        float mSplitSize = 8 * 1.0f;// 块块空隙的宽度
        float itemSize = 8 * 1.0f;// 每个块块的宽度

        // 根据块块的大小和空隙的大小求出块块的个数
        mCount = (int) (360 * 1.0f / (mSplitSize + itemSize));
        // 求余数,将余数分配到空隙
        float yu = (360 * 1.0f % (mSplitSize + itemSize));
        mSplitSize += yu / mCount;

        RectF oval = new RectF(centre - radius, centre - radius, centre
                + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(mStrokeWidth);
        mPaint.setColor(Color.parseColor("#B5B5B5")); // 设置圆环的颜色

        for (int i = 0; i < mCount; i++) {
            canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false,
                    mPaint); // 根据进度画圆弧
        }
        if (currentPosition == mCount - 1) {
            currentPosition = 0;
        }

        for (int i = 0; i < mCurrentCount; i++) {
            if (i==mCurrentCount-2) {
                mPaint.setColor(Color.parseColor("#70575757")); // 设置圆环的颜色
            }else if(i==mCurrentCount-1) {
                mPaint.setColor(Color.parseColor("#b4575757")); // 设置圆环的颜色
            }else{
                mPaint.setColor(Color.parseColor("#50575757")); // 设置圆环的颜色
            }
            canvas.drawArc(oval, (i + currentPosition)
                    * (itemSize + mSplitSize), itemSize, false, mPaint); // 根据进度画圆弧
        }
        currentPosition++;
        invalidate();
    }

}
发布了11 篇原创文章 · 获赞 1 · 访问量 3915

猜你喜欢

转载自blog.csdn.net/qin19930929/article/details/50681404