[置顶] Android自定义控件(二)——圆形进度条以及回调方法

(一)引言

上一篇博客介绍了Android自定义控件中音量控制器的实现方法,没有看过的盆友可以传送到http://blog.csdn.net/a253664942/article/details/45017283看看。今天准备给大家介绍一下圆形进度条的实现方式。
首先看一下最终的实现效果,来上图:
[置顶] Android自定义控件(二)——圆形进度条以及回调方法_第1张图片
进度条的背景进度的颜色、进度的颜色以及字体的颜色、圆环的半径和宽度都可以使用自定义属性来改变,另外,还添加了一个onProgressListener监听器,其中有一个onEnd回调方法,用来处理当进度条到达最大值时的事件。各位看官如果喜欢,也可以自己加一些回调方法,比如onStart方法用来监听到进度开始执行的回调方法。

(二)代码实现

1.自定义类

首先自定义一个CircleProgressView类继承View,然后声明各种属性:进度条的半径,宽度,颜色等以及回调函数。源码中有很详细的注释,一看就明白,这里就不再赘述了。

public class CircleProgressView extends View {

private Paint mPaintBackground; // 绘制背景圆环的画笔
private Paint mPaintProgress; // 绘制背景进度的画笔
private Paint mPaintText; // 绘制背景字体的画笔
private int bgColor = Color.WHITE; // 背景圆环的颜色
private int textColor = Color.CYAN; // 字体的颜色
private int progressColor = Color.CYAN; // 进度条的颜色
private float mStrokeWidth = 10;// 背景圆环的宽度
private float mRadius = 60; // 背景圆环的半径
private RectF rectPro;// 进度条的绘制外接矩形
private int mProgress = 0; // 当前进度
private int mMaxProgress = 100; // 最大进度
private int mWidth, mHeight;
private onProgressListener mOnProgressListener;

public void setOnProgressListener(onProgressListener mOnProgressListener) {
this.mOnProgressListener = mOnProgressListener;
}
/** * 回调接口 * */
public  interface onProgressListener{
/** * 回调函数 当进度条满时调用此方法 */
public void onEnd(); 
}

2.获得自定义属性

在构造方法中 获得xml文件中指定的自定义属性的值,以及初始化画笔。

public CircleProgressView(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub
        if(attrs!=null){
            TypedArray ta = context.obtainStyledAttributes(attrs,
                    R.styleable.CircleProgress);
            int count = ta.getIndexCount();
            for (int i = 0; i < count; i++) {
                int attr = ta.getIndex(i);
                switch (attr) {
                case R.styleable.CircleProgress_radius:
                    mRadius = ta.getDimension(R.styleable.CircleProgress_radius, mRadius);
                    break;
                case R.styleable.CircleProgress_strokeWidth:
                    mStrokeWidth = ta.getDimension(R.styleable.CircleProgress_strokeWidth, mStrokeWidth);
                    break;
                case R.styleable.CircleProgress_bgColor:
                    bgColor = ta.getColor(R.styleable.CircleProgress_bgColor, bgColor);
                    break;
                case R.styleable.CircleProgress_progressColor:
                    progressColor = ta.getColor(R.styleable.CircleProgress_progressColor, progressColor);
                    break;
                case R.styleable.CircleProgress_android_textColor:
                    textColor = ta.getColor(R.styleable.CircleProgress_android_textColor, textColor);
                    break;
                }
            }
            ta.recycle();
        }

        initPaint();
    }

initPaint方法是初始化画笔的函数。

private void initPaint() {
        mPaintBackground = new Paint();
        mPaintBackground.setColor(bgColor);
        // 设置抗锯齿
        mPaintBackground.setAntiAlias(true);
        // 设置防抖动
        mPaintBackground.setDither(true);
        // 设置样式为环形
        mPaintBackground.setStyle(Style.STROKE);
        // 设置环形的宽度
        mPaintBackground.setStrokeWidth(mStrokeWidth);

        mPaintProgress = new Paint();
        mPaintProgress.setColor(progressColor);
        // 设置抗锯齿
        mPaintProgress.setAntiAlias(true);
        // 设置防抖动
        mPaintProgress.setDither(true);
        // 设置样式为环形
        mPaintProgress.setStyle(Style.STROKE);
        // 设置环形的宽度
        mPaintProgress.setStrokeWidth(mStrokeWidth);

        mPaintText = new Paint();
        mPaintText.setColor(textColor);
        // 设置抗锯齿
        mPaintText.setAntiAlias(true);
        mPaintText.setTextAlign(Align.CENTER);
        mPaintText.setTextSize(40);

    }

progressColor、bgColor等都是自定义的属性,在attrs.xml文件中声明。见名知意,这些属性值的意思应该不难理解。

attrs.xml

<resources xmlns:android="http://schemas.android.com/apk/res/android">
    <attr name="bgColor" format="color|reference" />
    <attr name="progressColor" format="color|reference" />
    <attr name="radius" format="dimension" />
    <attr name="strokeWidth" format="dimension" />

    <declare-styleable name="CircleProgress">
        <attr name="android:textColor" />
        <attr name="bgColor" />
        <attr name="progressColor" />
        <attr name="radius" />
        <attr name="strokeWidth" />
    </declare-styleable>
</resources>

3.测量控件宽高

在onMeasure方法中测量控件的宽高,RectPro是进度条圆环外接矩形的范围。

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        mWidth = getRealSize(widthMeasureSpec);
        mHeight = getRealSize(heightMeasureSpec);
        setMeasuredDimension(mWidth, mHeight);
    }
private int getRealSize(int measureSpec) {
        int result = -1;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.UNSPECIFIED) { // 这两种模式需要自己计算
            result = (int) (mRadius * 2 + mStrokeWidth*2);
        } else {
            result = size;
        }
        return result;
    }
    private void initRect() {
        if (rectPro == null) {
            rectPro = new RectF();
            int viewSize = (int) (mRadius * 2);
            int left = (mWidth - viewSize) / 2;
            int top = (mHeight - viewSize) / 2;
            int right = left + viewSize;
            int bottom = top + viewSize;
            rectPro.set(left, top, right, bottom);
        }

这里可以画个图来便于大家理解。
[置顶] Android自定义控件(二)——圆形进度条以及回调方法_第2张图片
在上图中,黑色边框内的范围代表父容器。而我们的控件的宽度等于直径的长度+加上边框的宽度*2。即 width =radius *2 + strokeWidth*2;
高度同理。
绿色的边框表示RectPro即进度条圆环外接矩形的范围。RectPro的left和top的坐标等于控件的宽度减去圆环直径然后除以2;right和bottom的坐标等于left的坐标加上直径。

4.绘制进度条

测量完控件的宽高之后,来到最重要的一步:onDraw方法中绘制进度条。

protected void onDraw(Canvas canvas) {
        float angle = mProgress / (mMaxProgress * 1.0f) * 360; // 圆弧角度
        initRect();
        //绘制背景圆环
        canvas.drawCircle(mWidth / 2, mHeight / 2, mRadius,
                mPaintBackground);
        //绘制进度条
        canvas.drawArc(rectPro, -90, angle, false, mPaintProgress);
        //绘制字体
        canvas.drawText(mProgress + "%", mWidth / 2, mHeight / 2, mPaintText);
        if (mProgress < mMaxProgress) {
            mProgress += 2;
            invalidate();
        }
        //当进度到达最大值时 调用此函数
        if(mOnProgressListener != null){
        if(mProgress == mMaxProgress){
                mOnProgressListener.onEnd();
            }
        }

    }

我们控制进度条每次迭代2进度,只要进度条当前值小于最大值,则刷新视图重新绘制。最后,当进度条到达最大值时,我们调用回调方法。

5.使用自定义控件

在activity_main.xml中引用我们的自定义控件并设置属性。并在activity中使用我们的回调方法:当进度条到达最大值时,设置其进度为0,最终的效果时:进度条无限循环从0到100;

activity_main.xml

   <com.custom.circleprogressview.CircleProgressView
        android:id="@+id/pro"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:bgColor="#FFFF00"
        app:progressColor="#FF0F00"
        app:radius = "100dip"
        app:strokeWidth = "10dip"
       />

activity中调用

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final CircleProgressView progressView = (CircleProgressView) findViewById(R.id.pro);
        progressView.setOnProgressListener(new onProgressListener() {
            public void onEnd() {
                // TODO Auto-generated method stub
                progressView.setProgress(0);
            }

        });
    }

(三)总结

好了,收工!这次的自定义控件的实现中涉及到了很多的知识点:自定义属性的使用,自定义视图的绘制以及自己定义的回调接口。
其实大家可以发现,将这个案例改一改,我们就可以实现另外一种效果:小米音量控制器。很简单,只要将中间的字换成图片就可以了,然后改一下进度条的颜色~~
[置顶] Android自定义控件(二)——圆形进度条以及回调方法_第3张图片
各位如果喜欢的话,可以留个言 点个赞~!
**

附上源码

**

你可能感兴趣的:(android,自定义控件,进度条,接口回调)