本篇参考:GcsSloop的安卓自定义View进阶-Canvas之绘制图形
一、分析如上饼状图,所需要得信息如下
- 各块的颜色
- 所有块量得总和
- 各个块得量占总量的百分比,并通过百分比得到各个块所占扇形的弧度
- 第一个块得起始角度
- 该 View 控件的宽高及位置
二、具体控件逻辑
-
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省略 }
-
自定义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(); } } }
-
针对上述部分代码片的图解