android之自定义View和ViewGroup(四)(代码篇,实现圆形进度条)

好久不写博客,最近没任务就来写写博客,今天就写个简单的自定义圆形进度条的实现,最终效果如下:


好了,我们首先分析一下如果是你做这种效果需要哪些步骤呢?考虑几秒再看下面的。别偷懒。


你思考了么?这么快就来看步骤了,太懒了吧!

其实很简单,3个步骤,1.画中间绿色的圆形;2.画外面蓝色的进度(其实是一个扇形);3.画进度(图中的数字1%-99%、完成),画的绿色圆形将蓝色的扇形覆盖住,就是上图的效果了,然后慢慢改变蓝色扇形的角度就行了。具体实现步骤如下图:


是不是很简单?当然简单!

那么开始写具体实现代码!

首先自定义一个类继承自View,实现构造方法初始化:扇形,绿色圆形,字,这三个属性所需的画笔(我用了三个画笔是为了区分大家方便看,当然也可以只用一个画笔就行了)

package com.custom.my.widget;

public class CircleProgressBar extends View {
	
	private Context context;
	private int height,width;  //自定义控件的宽高
	private float progress;  //进度

	private Paint paint;  //蓝色扇形所需的画笔
	private Paint bkPaint;  //绿色圆形所需的画笔
	private Paint tvPaint;  //圆里面的进度字所需的画笔
	private Rect mBound;  //用于获取字体的大小

	public CircleProgressBar(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		this.paint = new Paint();
		this.bkPaint = new Paint();
		this.tvPaint = new Paint();
		this.mBound = new Rect();
		init();
	}

	private void init(){
		paint.setStyle(Style.FILL);
		paint.setColor(Color.parseColor("#50A3FE"));
		paint.setAntiAlias(true);

		bkPaint.setStyle(Style.FILL);
		bkPaint.setColor(Color.parseColor("#00ff00"));
		bkPaint.setAntiAlias(true);

		tvPaint.setColor(Color.parseColor("#ffffff"));
		tvPaint.setTextSize(15);
	}

}
画笔等属性初始化完成后,我们需要获取我们设置的宽高(这个圆形进度条的整体宽高),而我们获取View宽高的地方是重写View的onMeasure方法:

//获取当前控件的高度和宽度,单位是像素
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		height = MeasureSpec.getSize(heightMeasureSpec);
		width = MeasureSpec.getSize(widthMeasureSpec);
	}
获取到了宽高后我们就可以开始画了,在CircleProgressBar 的onDraw方法里面画扇形,圆形,字。

private float set2Degree(float sendFt){   //将进度的数值变为弧度数值,进度100,弧度有360,所以比例是3.6
		return sendFt*3.6f;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if(width*height==0){
			return;
		}
		canvas.drawArc(new RectF(0, 0, width, height), 270, set2Degree(progress), true, paint);  //画蓝色扇形
		canvas.drawCircle(width / 2, height / 2, width / 2 - 5, bkPaint);  //画绿色圆形,半径比蓝色扇形的小5px
		if(progress < 100){   //进度没达到100%时显示进度
			String strPro = String.valueOf((int)progress)+"%";
			tvPaint.getTextBounds(strPro,0,strPro.length(),mBound);
			canvas.drawText(strPro,width/2 - mBound.width()/2,height/2 + mBound.height()/2,tvPaint);
		}else{  //达到100%后显示完成
			String text = "完成";
			tvPaint.getTextBounds(text,0,text.length(),mBound);
			canvas.drawText(text,width/2 - mBound.width()/2,height/2 + mBound.height()/2,tvPaint);
		}
	}
当然画了后我们要实时更新弧度,所以我们在CircleProgressBar 里面加个public方法来实时更新进度。

public void setProgress(float progress){
		this.progress = progress;
		postInvalidate();
	}
当进度发生改变后调用改方法修改进度即可。使用用例如下:

xml布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.custom.my.activity.CircleProgressAcitivity">

    <com.custom.my.widget.CircleProgressBar
        android:id="@+id/circle_progress"
        android:layout_centerInParent="true"
        android:layout_width="65dp"
        android:layout_height="65dp" />

</RelativeLayout>
Activity中如下,为了模拟进度,我们使用handler来不停地更新进度:

public class CircleProgressAcitivity extends AppCompatActivity {

    private CircleProgressBar circleProgressBar;
    private float progress = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_circle_progress);

        circleProgressBar = (CircleProgressBar) findViewById(R.id.circle_progress);
        handler.sendEmptyMessageDelayed(1,100);
    }

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            if(msg.what == 1){
                if(progress <= 99){
                    ++progress;
                    circleProgressBar.setProgress(progress);  //更新进度条
                    this.sendEmptyMessageDelayed(1, 100);
                }
            }
        }
    };
}

完成了,整个思路很简单,代码也很简单,当然如果想自定义字体的颜色,字体大小等,可以结合之前我写的那个自定义条形进度条的那篇博客http://blog.csdn.net/gsw333/article/details/50803313就行,当然如果觉得太丑也可以把中间的绿色换成一个beautiful图片就行了,反正做法都是一样。


最后最后最后!!!!!!!!!!如果你觉得不错帮我顶一顶!!!!!!!!!如果觉得不好,请给我的辛苦码字顶一顶!!!!!!!!!



发布了33 篇原创文章 · 获赞 49 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/gsw333/article/details/51491004