Android 自定義餅狀圖


github 地址:https://github.com/dkest/PieView

簡單分析

  其實根據我們上面的知識已經能自己制作一個餅狀圖了。不過制作東西最重要的不是制作結果,而是制作思路。 相信我貼上代碼大家一看就立刻明白了,非常簡單的東西。不過嘛,咱們還是想了解一下制作思路:

先分析餅狀圖的構成,非常明顯,餅狀圖就是一個又一個的扇形構成的,每個扇形都有不同的顏色,對應的有名字,數據和百分比。

經以上信息可以得出餅狀圖的最基本數據應包括:名字 數據值 百分比 對應的角度 顏色。

  用戶關心的數據 : 名字 數據值 百分比
  需要程序計算的數據: 百分比 對應的角度
  其中顏色這一項可以用戶指 

 

 1 public class PieData {  2 
 3     private String name;        // 名字
 4     private float value;        // 數值
 5     private float percentage;   // 百分比
 6 
 7     private int color = 0;      // 顏色
 8     private float angle = 0;    // 角度
 9 
10     public PieData(@NonNull String name, @NonNull float value) { 11         this.name = name; 12         this.value = value; 13  } 14 }

 

 

 

自定義View:

先按照自定義View流程梳理一遍(確定各個步驟應該做的事情):

步驟 關鍵字 作用
1 構造函數 初始化(初始化畫筆Paint)
2 onMeasure 測量View的大小(暫時不用關心)
3 onSizeChanged 確定View大小(記錄當前View的寬高)
4 onLayout 確定子View布局(無子View,不關心)
5 onDraw 實際繪制內容(繪制餅狀圖)
6 提供接口 提供接口(提供設置數據的接口)

代碼如下:

 

 1 public class PieView extends View {
 2     // 顏色表
 3     private int[] mColors = {0xFFCCFF00, 0xFF6495ED, 0xFFE32636, 0xFF800000, 0xFF808000, 0xFFFF8C69, 0xFF808080,
 4             0xFFE6B800, 0xFF7CFC00};
 5     // 餅狀圖初始繪制角度
 6     private float mStartAngle = 0;
 7     // 數據
 8     private ArrayList<PieData> mData;
 9     // 寬高
10     private int mWidth, mHeight;
11     // 畫筆
12     private Paint mPaint = new Paint();
13 
14     public PieView(Context context) {
15         this(context, null);
16     }
17 
18     public PieView(Context context, AttributeSet attrs) {
19         super(context, attrs);
20         mPaint.setStyle(Paint.Style.FILL);
21         mPaint.setAntiAlias(true);
22     }
23 
24     @Override
25     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
26         super.onSizeChanged(w, h, oldw, oldh);
27         mWidth = w;
28         mHeight = h;
29     }
30 
31     @Override
32     protected void onDraw(Canvas canvas) {
33         super.onDraw(canvas);
34         if (null == mData)
35             return;
36         float currentStartAngle = mStartAngle;                    // 當前起始角度
37         canvas.translate(mWidth / 2, mHeight / 2);                // 將畫布坐標原點移動到中心位置
38         float r = (float) (Math.min(mWidth, mHeight) / 2 * 0.8);  // 餅狀圖半徑
39         RectF rect = new RectF(-r, -r, r, r);                     // 餅狀圖繪制區域
40 
41         for (int i = 0; i < mData.size(); i++) {
42             PieData pie = mData.get(i);
43             mPaint.setColor(pie.getColor());
44             canvas.drawArc(rect, currentStartAngle, pie.getAngle(), true, mPaint);
45             currentStartAngle += pie.getAngle();
46         }
47 
48     }
49 
50     // 設置起始角度
51     public void setStartAngle(int mStartAngle) {
52         this.mStartAngle = mStartAngle;
53         invalidate();   // 刷新
54     }
55 
56     // 設置數據
57     public void setData(ArrayList<PieData> mData) {
58         this.mData = mData;
59         initDate(mData);
60         invalidate();   // 刷新
61     }
62 
63     // 初始化數據
64     private void initDate(ArrayList<PieData> mData) {
65         if (null == mData || mData.size() == 0)   // 數據有問題 直接返回
66             return;
67 
68         float sumValue = 0;
69         for (int i = 0; i < mData.size(); i++) {
70             PieData pie = mData.get(i);
71 
72             sumValue += pie.getValue();       //計算數值和
73 
74             int j = i % mColors.length;       //設置顏色
75             pie.setColor(mColors[j]);
76         }
77 
78         float sumAngle = 0;
79         for (int i = 0; i < mData.size(); i++) {
80             PieData pie = mData.get(i);
81 
82             float percentage = pie.getValue() / sumValue;   // 百分比
83             float angle = percentage * 360;                 // 對應的角度
84 
85             pie.setPercentage(percentage);                  // 記錄百分比
86             pie.setAngle(angle);                            // 記錄角度大小
87             sumAngle += angle;
88 
89             Log.i("angle", "" + pie.getAngle());
90         }
91     }
View Code

PS: 在更改了數據需要重繪界面時要調用invalidate()這個函數重新繪制。

效果圖

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM