自定义饼状View

自定义View的基本步骤是重写onMeasure方法及测量、onlayout方法及布局、ondraw方法及绘制,这三大步骤,但是当onMeasure方法被调用完后,控件大小发生变化会执行onSizeChanged,我们可以在这个方法里面做一下计算和配置

自定义View其实真正需要重写的方法是onMeasure和ondraw方法,在自定义ViewGroup的时候才需要onlayout方法,

画一个饼状图,里面有不同的占比,旁边会有个举行图显示占比

看到这张图

第一,继承view,申明构造方法

 

public WxbView(Context context) {
    this(context, null);
}

public WxbView(Context context, @Nullable AttributeSet attrs) {
    this(context, attrs, 0);
}

public WxbView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr); 
}

第二,重写onMeasure和ondraw、onSizeChanged方法

 

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int wmode = MeasureSpec.getMode(widthMeasureSpec);
    int wsize = MeasureSpec.getSize(widthMeasureSpec);
    int hmode = MeasureSpec.getMode(heightMeasureSpec);
    int hsize = MeasureSpec.getSize(heightMeasureSpec);
    mWidth=getSize(wmode,400f,wsize);
    mHeight=getSize(hmode,200f,hsize);
    //存储测量好的宽和高
    setMeasuredDimension(wsize,hsize);

}

private int getSize(int mode, float size, int msize) {
    int value = 0;
    switch (mode) {
        case MeasureSpec.EXACTLY:
            value = msize;
            break;
        case MeasureSpec.AT_MOST:
            value = DpUtil.dip2px(context, size);
            break;
        case MeasureSpec.UNSPECIFIED:
            break;
        default:
            break;
    }

    return value;

}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mR=Math.min(mWidth,mHeight);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
   
}

第三,定义圆的直径、view的宽和高、绘制文字的坐标、矩形的宽度和高度、圆到矩形的距离等

 

private List<Bean> list;//饼状圆的数据

private RectF mRectF;//圆矩形

private RectF iRect;//右边的矩形

private Paint mPaint;//画笔

private int mWidth, mHeight;

private float rotateDegree;//每个圆的起始角度

private float sumValue;//所有值的和

private float mR;//圆的直径

private float textY;//绘制文字的Y坐标

private float mRectFHeight = 40;//矩形的高度

private float mRectFWidth = 80;//矩形的宽度

private float mMargin = 40;//矩形到圆的距离

private Context context;

第四,准备好Paint画笔,RectF矩形,并初始化

 

private void init() {
    list = new ArrayList<>();
    mRectF = new RectF();
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
}

第五,绘制时计算每个区域绘制的起始位及具体绘制

 

//设置圆形绘制的范围
mRectF.set(0,0,mR,mR);
//画布中心X坐标向右移动(控件宽度-圆直径)之差的八分之一的距离
//画布中心Y坐标向下移动(控件高度-圆直径)之差的二分之一的距离
canvas.translate((mWidth-mR)/8,(mHeight-mR)/2);
if (list.size()>0&&Float.compare(sumValue,0.0f)!=0){
    for (int i=0;i<list.size();i++){
        Bean bean=list.get(i);
        //画圆弧
        mPaint.setColor(bean.getColor());
        canvas.drawArc(mRectF,rotateDegree,bean.getDegree(),true,mPaint);
        rotateDegree+=bean.getDegree();
        //画矩形和文字
        drawRectAntText(canvas,bean);
    }
}

矩形的起始位置及具体绘制

 

private void  drawRectAntText(Canvas canvas,Bean bean){
    iRect=new RectF();
    //设置画矩形的范围
    float left=mR+mMargin;
    float right=mR+mMargin+mRectFWidth;
    float bottom=textY+mRectFHeight;
    iRect.set(left,textY,right,bottom);
    canvas.drawRect(iRect,mPaint);
    //设置颜色
    mPaint.setColor(Color.BLACK);
    //设置文字大小
    mPaint.setTextSize(30);
    //画文字
    canvas.drawText(bean.getName()+"("+new DecimalFormat(".00").format(bean.getValue()/sumValue*100)+"%)",right+10,textY+30,mPaint);
    textY+=mRectFHeight;
}

第六,设置绘制数据

 

public void setData(List<Bean> list){

    if (list==null||list.size()<=0){
        return;
    }
    for (int i=0;i<list.size();i++){
        Bean bean=list.get(i);
        sumValue+=bean.getValue();
        bean.setDegree(bean.getValue());
    }
    for (int i=0;i<list.size();i++){
        Bean bean=list.get(i);
        bean.setDegree(bean.getValue()/sumValue*360);
        this.list.add(bean);
    }
    invalidate();
}

以上一个饼状图就绘制完成了

对应的bean

public class Bean {
    private String name;


    private int color;

    private float value;

    private float degree;

    public int getColor() {
        return color;
    }

    public void setColor(int color) {
        this.color = color;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getValue() {
        return value;
    }

    public void setValue(float value) {
        this.value = value;
    }

    public float getDegree() {
        return degree;
    }

    public void setDegree(float degree) {
        this.degree = degree;
    }
}

 

对应的自定义View

 

public class WxbView extends View {

    private List<Bean> list;//饼状圆的数据

    private RectF mRectF;//圆矩形

    private RectF iRect;//右边的矩形

    private Paint mPaint;//画笔

    private int mWidth, mHeight;

    private float rotateDegree;//每个圆的起始角度

    private float sumValue;//所有值的和

    private float mR;//圆的直径

    private float textY;//绘制文字的Y坐标

    private float mRectFHeight = 40;//矩形的高度

    private float mRectFWidth = 80;//矩形的宽度

    private float mMargin = 40;//矩形到圆的距离

    private Context context;


    public WxbView(Context context) {
        this(context, null);
    }

    public WxbView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WxbView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init();
    }

    private void init() {
        list = new ArrayList<>();
        mRectF = new RectF();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int wmode = MeasureSpec.getMode(widthMeasureSpec);
        int wsize = MeasureSpec.getSize(widthMeasureSpec);
        int hmode = MeasureSpec.getMode(heightMeasureSpec);
        int hsize = MeasureSpec.getSize(heightMeasureSpec);
        mWidth=getSize(wmode,400f,wsize);
        mHeight=getSize(hmode,200f,hsize);
        //存储测量好的宽和高
        setMeasuredDimension(wsize,hsize);

    }

    private int getSize(int mode, float size, int msize) {
        int value = 0;
        switch (mode) {
            case MeasureSpec.EXACTLY:
                value = msize;
                break;
            case MeasureSpec.AT_MOST:
                value = DpUtil.dip2px(context, size);
                break;
            case MeasureSpec.UNSPECIFIED:
                break;
            default:
                break;
        }

        return value;

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mR=Math.min(mWidth,mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //设置圆形绘制的范围
        mRectF.set(0,0,mR,mR);
        //画布中心X坐标向右移动(控件宽度-圆直径)之差的八分之一的距离
        //画布中心Y坐标向下移动(控件高度-圆直径)之差的二分之一的距离
        canvas.translate((mWidth-mR)/8,(mHeight-mR)/2);
        if (list.size()>0&&Float.compare(sumValue,0.0f)!=0){
            for (int i=0;i<list.size();i++){
                Bean bean=list.get(i);
                //画圆弧
                mPaint.setColor(bean.getColor());
                canvas.drawArc(mRectF,rotateDegree,bean.getDegree(),true,mPaint);
                rotateDegree+=bean.getDegree();
                //画矩形和文字
                drawRectAntText(canvas,bean);
            }
        }
    }

    private void  drawRectAntText(Canvas canvas,Bean bean){
        iRect=new RectF();
        //设置画矩形的范围
        float left=mR+mMargin;
        float right=mR+mMargin+mRectFWidth;
        float bottom=textY+mRectFHeight;
        iRect.set(left,textY,right,bottom);
        canvas.drawRect(iRect,mPaint);
        //设置颜色
        mPaint.setColor(Color.BLACK);
        //设置文字大小
        mPaint.setTextSize(30);
        //画文字
        canvas.drawText(bean.getName()+"("+new DecimalFormat(".00").format(bean.getValue()/sumValue*100)+"%)",right+10,textY+30,mPaint);
        textY+=mRectFHeight;
    }
    public void setData(List<Bean> list){

        if (list==null||list.size()<=0){
            return;
        }
        for (int i=0;i<list.size();i++){
            Bean bean=list.get(i);
            sumValue+=bean.getValue();
            bean.setDegree(bean.getValue());
        }
        for (int i=0;i<list.size();i++){
            Bean bean=list.get(i);
            bean.setDegree(bean.getValue()/sumValue*360);
            this.list.add(bean);
        }
        invalidate();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值