最近公司做项目的时候遇到一个需求,市场分布要用饼状图来显示。网上找了几个感觉都不是很符合需求。正当愁眉苦脸的时候,产品突然说不需要这个需求了。然后就这么放下来了。现在就自己琢磨着是不是尝试自己写一个出来。会在这里慢慢更新,如果有什么问题可以直接提出来。楼主小白一枚。在慢慢摸索!
首先需要说一下的是本文适合新手小白来看,基础较好的人可能会觉得太过于简单。
先上一个最终需要实现的效果。
但是目前的显示效果是:
这个是饼状图最简单的显示方式,上面没有任何表示。只是一个单纯的颜色显示。
理想和现实的差距是不是特别明显。但是还是要上一下代码,毕竟没代码哔哔啥!
public class PieChartView extends View {
// 默认的颜色
private int[] mColors = {0xFF00FF00, 0xFFFF0000, 0xFF0000FF, 0xFF0F0F0F, 0xFFF0F0F0, 0xFFFF0F0F, 0xFFFFFFFF,
0xFFEEEEEE, 0xFFBBBBBB};
// 饼状图从哪里开始绘制
private float mStartAngle = 0;
// 需要的数据
private ArrayList<PieData> mData;
// 宽高
private int mWidth, mHeight;
// 画笔
private Paint mPaint = new Paint();
private float value;
public PieChartView(Context context) {
this(context, null);
}
public PieChartView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PieChartView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//设置绘画模式
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
//设置抗锯齿
mPaint.setAntiAlias(true);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mData == null) {
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 < mData.size(); i++) {
PieData pie = mData.get(i);
mPaint.setColor(pie.getColor());
canvas.drawArc(rect, currentStartAngle, pie.getAngle(), true, mPaint);
currentStartAngle += pie.getAngle();
}
}
/**
* 设置数据的方法
*
* @param data
*/
public void setmData(ArrayList<PieData> data) {
this.mData = data;
initData(mData);
invalidate();
}
/**
* 设置颜色的方法
*
* @param mColors
*/
public void setmColors(int[] mColors) {
this.mColors = mColors;
invalidate();
}
/**
* 设置从哪儿开始绘画
*
* @param startAngle
*/
public void setmStartAngle(int startAngle) {
this.mStartAngle = startAngle;
invalidate();
}
/**
* 初始化数据的方法
*
* @param data
*/
private void initData(ArrayList<PieData> data) {
if (data == null || data.size() == 0) {
return;
}
float sumValue = 0;
for (int i = 0; i < data.size(); i++) {
PieData pieData = data.get(i);
sumValue += pieData.getValue();
int color = i % mColors.length;
pieData.setColor(mColors[color]);
}
float sumAngle = 0;
for (int i = 0; i < data.size(); i++) {
PieData pieData = data.get(i);
float percentage = pieData.getValue() / sumValue;
pieData.setPercentage(percentage);
pieData.setAngle(percentage * 360);
sumAngle += percentage * 360;
}
}
}
可以看出来.当开始角度是0的时候,系统是从三点钟方向开始顺时针绘画.
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;
}
MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pieChartView = (PieChartView) findViewById(R.id.pie_chart);
pieChartView.setmStartAngle(180);
int[] colors = {0xFFFF0000, 0xFF00FF00, 0xFF0000FF};
pieChartView.setmColors(colors);
for (int i = 0; i < 5; i++) {
switch (i) {
case 0:
mDatas.add(new PieData("语文",100));
break;
case 1:
mDatas.add(new PieData("数学",200));
break;
case 2:
mDatas.add(new PieData("英语",150));
break;
case 3:
mDatas.add(new PieData("物理",100));
break;
case 4:
mDatas.add(new PieData("化学",120));
break;
}
}
pieChartView.setmData(mDatas);
}
比较值得注意的几个点就是绘画的时候要注意到百分比的计算和颜色的分配。这个view比较简单,相信代码贴上来基本都能看懂。没什么需要单独去解释的,如果有什么问题,请大家留言或者私信。本文会持续更新。直到达到最终效果。么么哒!