阿里云实在是太坑了,决定把博客搬到csdn来,为自己的钱包省省钱。
为自己的android程序自定义漂亮个性View是每一个Android程序员必须学会的事情,今天来讲解一下如何通过自定义View来实现CircleBar的效果。
效果图:
进度条绘制
试问把大象装进冰箱有几步?答曰:三步
处理布局
谈到处理布局就不得不谈到view的绘制周期
1. onFinishInflate
2. onAttachedToWindow
3. onMeasure
4. onSizeChanged
5. onLayout
6. onDraw
以上个这个几个方法的作用不再做详细介绍,一般涉及布局的处理我们会使用onMeasure、onSizeChanged或者onLayout。这里我们使用onSizeChanged方法。
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
onSizeChanged这个方法会传入四个参数,看名字也能理解出来,前两个是改变后的宽高,后两个是改变前的宽高。这里我们只需要处理一下新的宽高就可以了。
这里我们就先拿两个变量保存起来,等会绘制的时候再说。
内容绘制
伟大的共产主义战士毛泽东同志曾经说过:路线错误,知识越多越反动。所以我们在设计时就要明确我们的思路,如何绘制一个能转动的进度条?
思路有两种:
第一种是【大圆】->【饼状图】->【小圆】覆盖的形式
首先绘制一个大圆
canvas.drawCircle(middleX, middleY, radius, paint1);
在大圆上面绘制一个半径相同的饼状图,需要设置圆心。curPercent是进度值
canvas.drawArc(rect, 270, (int) (3.6 * curPercent), true, paint2);
然后再覆盖比大圆小一点的圆,小圆的半径比大圆小0.1×radius的宽度。
canvas.drawCircle(middleX, middleY, (float) (radius - (0.1 * radius)), paint1);
这里会有一个问题,在布局时,长宽往往不一定相等。这是我们就比较两者,取小的一方作为直径。
middleX = w / 2;
middleY = h / 2;
if(middleY > middleX){
radius = middleX;
center = middleX;
}else {
radius = middleY;
center = middleY;
}
之前的curPercent有三种值,分别为0、1~99、100。代表三种状态,开始、进行中、结束。因此我们根据值的大小进行绘制。
完整代码
public class CircleBar extends View{
private int radius;
private int center;
private int middleX;
private int middleY;
private int curPercent = 0;
private Bitmap bitmap;
private Bitmap newBitMap;
private RectF rect;
private Paint paint1 = new Paint();
private Paint paint2 = new Paint();
private Paint paint3 = new Paint();
private Path path;
private int color1 = Color.rgb(0,204,204);
private int color2 = Color.rgb(204,255,255);
private int color3 = Color.BLACK;
public CircleBar(Context context) {
super(context);
}
public CircleBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CircleBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
getLayout(w,h);
invalidate();
}
private void getLayout(int w, int h) {
middleX = w / 2;
middleY = h / 2;
if(middleY > middleX){
radius = middleX;
center = middleX;
}else {
radius = middleY;
center = middleY;
}
rect = new RectF(0 ,0 ,(int)(radius * 2),(int)(radius * 2));
rect.offset(middleX-radius,middleY-radius);
}
private void initPaint(){
paint1.setAntiAlias(true);
paint2.setAntiAlias(true);
paint3.setAntiAlias(true);
paint1.setColor(color1);
paint2.setColor(color2);
paint3.setColor(color3);
paint3.setStyle(Paint.Style.STROKE);
paint3.setStrokeWidth(8);
}
protected void onDraw(Canvas canvas) {
initPaint();
//背景圆
canvas.drawCircle(middleX, middleY, radius, paint1);
//饼状图
canvas.drawArc(rect, 270, (int) (3.6 * curPercent), true, paint2);
//小圆
canvas.drawCircle(middleX, middleY, (float) (radius - (0.1 * radius)), paint1);
//图标
if(curPercent == 0){
canvas.drawLine(radius / 2,radius / 2,(float) (1.5 * radius),radius,paint3);
canvas.drawLine(radius / 2,radius / 2,radius / 2,(float) (1.5 * radius),paint3);
canvas.drawLine(radius / 2,(float) (1.5 * radius),(float) (1.5 * radius),radius,paint3);
}else if(curPercent == 100){
canvas.drawLine(radius / 2, radius,radius, (float) (1.5 * radius),paint3);
canvas.drawLine(radius, (float) (1.5 * radius),(float) (1.5 * radius), radius / 2,paint3);
}else{
canvas.drawLine((float) (0.75 * radius), radius / 2,(float) (0.75 * radius), (float) (1.5 * radius),paint3);
canvas.drawLine((float) (1.25 * radius), radius / 2,(float) (1.25 * radius), (float) (1.5 * radius),paint3);
}
super.onDraw(canvas);
}
public void setCurPercent(int curPercent) {
if(curPercent>=0 && curPercent <= 100) {
this.curPercent = curPercent;
invalidate();
}
}
public void setColor(int color1,int color2,int color3){
this.color1 = color1;
this.color2 = color2;
this.color3 = color3;
}
public int getCurPercent(){
return this.curPercent;
}
}