最近公司做項目的時候遇到一個需求雨效,市場分布要用餅狀圖來顯示迅涮。網(wǎng)上找了幾個感覺都不是很符合需求。正當愁眉苦臉的時候徽龟,產品突然說不需要這個需求了叮姑。然后就這么放下來了。現(xiàn)在就自己琢磨著是不是嘗試自己寫一個出來据悔。會在這里慢慢更新传透,如果有什么問題可以直接提出來。樓主小白一枚屠尊。在慢慢摸索旷祸!
首先需要說一下的是本文適合新手小白來看,基礎較好的人可能會覺得太過于簡單讼昆。
先上一個最終需要實現(xiàn)的效果托享。
最終效果.jpg
最終效果2.jpg
但是目前的顯示效果是:
初始顯示效果
這個是餅狀圖最簡單的顯示方式,上面沒有任何表示浸赫。只是一個單純的顏色顯示闰围。
理想和現(xiàn)實的差距是不是特別明顯。但是還是要上一下代碼既峡,畢竟沒代碼嗶嗶啥羡榴!
public class PieChartView extends View {
// 默認的顏色
private int[] mColors = {0xFF00FF00, 0xFFFF0000, 0xFF0000FF, 0xFF0F0F0F, 0xFFF0F0F0, 0xFFFF0F0F, 0xFFFFFFFF,
0xFFEEEEEE, 0xFFBBBBBB};
// 餅狀圖從哪里開始繪制
private float mStartAngle = 0;
// 需要的數(shù)據(jù)
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); // 餅狀圖繪制區(qū)域
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();
}
}
/**
* 設置數(shù)據(jù)的方法
*
* @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();
}
/**
* 初始化數(shù)據(jù)的方法
*
* @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;
}
}
}
繪畫開始角度.png
可以看出來.當開始角度是0的時候,系統(tǒng)是從三點鐘方向開始順時針繪畫.
PieData 需要的數(shù)據(jù)
這個只是模擬的數(shù)據(jù),以及以后需要在餅狀圖上顯示的數(shù)據(jù).
private String name; //數(shù)據(jù)的名稱
private float value; //數(shù)據(jù)的值
/*------------------我是華麗的分割線------------------*/
private float percentage; //每個數(shù)據(jù)占總數(shù)的百分比
private int color = 0; // 數(shù)據(jù)在餅狀圖的顏色
private float angle = 0; //數(shù)據(jù)在圖中所占的角度
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("數(shù)學",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比較簡單运敢,相信代碼貼上來基本都能看懂校仑。沒什么需要單獨去解釋的忠售,如果有什么問題,請大家留言或者私信迄沫。本文會持續(xù)更新稻扬。直到達到最終效果。么么噠羊瘩!