好久不写博客,最近没任务就来写写博客,今天就写个简单的自定义圆形进度条的实现,最终效果如下:
好了,我们首先分析一下如果是你做这种效果需要哪些步骤呢?考虑几秒再看下面的。别偷懒。
你思考了么?这么快就来看步骤了,太懒了吧!
其实很简单,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布局:
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图片就行了,反正做法都是一样。
最后最后最后!!!!!!!!!!如果你觉得不错帮我顶一顶!!!!!!!!!如果觉得不好,请给我的辛苦码字顶一顶!!!!!!!!!