自定义饼状图控件PieView

来源:互联网 发布:巴黎住宿攻略 知乎 编辑:程序博客网 时间:2024/05/22 01:28

本篇参考:GcsSloop的安卓自定义View进阶-Canvas之绘制图形


这里写图片描述

一、分析如上饼状图,所需要得信息如下

  1. 各块的颜色
  2. 所有块量得总和
  3. 各个块得量占总量的百分比,并通过百分比得到各个块所占扇形的弧度
  4. 第一个块得起始角度
  5. 该 View 控件的宽高及位置

二、具体控件逻辑

  1. javabean

    public class PieData {    // 用户操作数据    private String name;        // 名字    private float value;        // 数值    private float percentage;   // 百分比    // 非用户操作数据    private int color = 0;      // 颜色    private float angle = 0;    // 角度    public PieData(String name, float value) {        this.name = name;        this.value = value;    }    ... // set/get省略}
  2. 自定义PieView

    public class PieView extends View {    // 1. 各块的颜色    private int[] mColors = {0xFFCCFF00, 0xFF6495ED, 0xFFE32636, 0xFF800000, 0xFF808000, 0xFFFF8C69, 0xFF808080, 0xFFE6B800, 0xFF7CFC00};    // 2. 第一块的初始角度    private float mStartAngle = 180;    // 数据集合    private ArrayList<PieData> mDatas;    // 控件宽高    private int mWidth, mHeight;    // 画笔    private Paint mPaint = new Paint();    public PieView(Context context) {        this(context, null);    }    public PieView(Context context, AttributeSet attrs) {        super(context, attrs);        mPaint.setStyle(Paint.Style.FILL);        mPaint.setAntiAlias(true);    }    // 记录当前View控件的宽高    @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mWidth = w;        mHeight = h;    }    // 设置起始角度并刷新界面    public void setStartAngle(int mStartAngle) {        this.mStartAngle = mStartAngle;        invalidate();    }    // 设置数据并刷新界面    public void setData(ArrayList<PieData> mData) {        this.mDatas = mData;        initData(mData);        invalidate();    }    // 饼状图中数据的处理    float sumValue = 0;       // 所有块的数据总量    float piePercentage = 0;  // 各块占数据总量的百分比    float sumAngle = 0;       // 所有块占的总扇形角度    float pieAngle = 0;       // 各块占的扇形角度    private void initData(ArrayList<PieData> mDatas) {        // 判空        if (null == mDatas || mDatas.size() == 0) {            return;        }        for (int i = 0; i < mDatas.size(); i++) {            PieData pie = mDatas.get(i);            // 1. 设置各块颜色            int j = i % mColors.length;            pie.setColor(mColors[j]);            // 2. 统计所有块的数据总量            sumValue += pie.getValue();            // 3. 计算各块量占总量的百分比            piePercentage = pie.getValue() / sumValue;            // 4. 通过各块量的占比计算所占扇形角度            pieAngle = piePercentage * 360;            pie.setPercentage(piePercentage);            pie.setAngle(pieAngle);            sumAngle += pieAngle;        }    }    @Override protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        // 判空        if (null == mDatas || mDatas.size() == 0) {            return;        }        // 记录当前起始角度        float currentStartAngle = mStartAngle;        // 将画布坐标原点移动到中心        canvas.translate(mWidth / 2, mHeight / 2);        // 饼状图半径        float r = (float) (Math.min(mWidth, mHeight) / 2 * 0.8);        // 确定饼状图绘制的区域        RectF rect = new RectF(-r, -r, r, r);        for (int i = 0; i < mDatas.size(); i++) {            PieData pie = mDatas.get(i);            mPaint.setColor(pie.getColor());            canvas.drawArc(rect, currentStartAngle, pie.getAngle(), true, mPaint);            currentStartAngle += pie.getAngle();        }    }}
  3. 针对上述部分代码片的图解

    这里写图片描述

原创粉丝点击