自定义view构建CircleBar

本文介绍如何在Android程序中自定义View以创建CircleBar效果。内容包括自定义View的绘制周期,如onMeasure、onSizeChanged和onDraw方法的使用,以及实现旋转进度条的两种思路和完整代码。
摘要由CSDN通过智能技术生成

阿里云实在是太坑了,决定把博客搬到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);


设计构思好了,现在让我们回到布局的处理中来,因为我们需要绘制的是一个圆,所以必须需要半径和圆心。在画布上,左上角的坐标是(0,0),所以我们把长宽的一半作为圆心。

这里会有一个问题,在布局时,长宽往往不一定相等。这是我们就比较两者,取小的一方作为直径。

        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;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值