服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android自定义控件实现饼状图

Android自定义控件实现饼状图

2022-09-07 15:38王世晖 Android

这篇文章主要为大家详细介绍了Android自定义控件实现饼状图,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实现一个如图所示的控件,包括两部分,左边的饼状图和中间的两个小方块,及右边的两行文字

Android自定义控件实现饼状图

实现起来比较简单,只是一些绘图API的调用

核心代码在onDraw函数里边,对静态控件进行绘制即可

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
@Override
protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 /**
 * 饼状图的x坐标
 */
 float centreX= getWidth()/5;
 /**
 * 饼状图的y坐标
 */
 float centreY= getHeight()/2;
 /**
 * 文字的大小
 */
 float textSize=getHeight()/7;
 float width=(float)getWidth();
 float height=(float)getHeight();
 /**
 * 中间小正方形边长的一半
 */
 float halfSmallRec =((float)getHeight())*3/70;
 percent =((float) mBigBallNumber)/(mBigBallNumber + mSmallBallNumber);
 /**
 * 求饼状图的半径
 */
 radius= Math.min(getWidth() * 1 / 8, getHeight() * 10 / 35);
 /**
 * 构建一个正方形,饼状图是这个正方形的内切圆
 */
 rectf=new RectF((int)(centreX-radius),(int)(centreY-radius),(int)(centreX+radius),(int)(centreY+radius));
 /**
 * 设置饼状图画笔的颜色,先绘制大球占的比例
 */
 piePaint.setColor(mBigBallColor);
 /* The arc is drawn clockwise. An angle of 0 degrees correspond to the
 * geometric angle of 0 degrees (3 o'clock on a watch.)*/
 /* drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)*/
 /**
 * 绘制大球的扇形图,float startAngle起始角度的0度的位置在3点钟方向
 * 因此大球的扇形图要从12点钟开始绘制,所以起始角度为270度
 */
 canvas.drawArc(rectf, 270, 360 * percent, true, piePaint);
 /**
 * 换种颜色,开始绘制小球占的饼状图
 */
 piePaint.setColor(mSmallBallColor);
 /**
 * 起始角度就是12点钟加上360度乘以大球占的比例,12点钟转换为起始角度为270度
 */
 canvas.drawArc(rectf, 270 + 360 * percent, 360 - 360 * percent, true, piePaint);
 颜色更改为大球的颜色*/
 piePaint.setColor(mBigBallColor);
 /**
 * 绘制上边的小方块,也就是大球的方块
 */
 canvas.drawRect(width * 2 / 5 - halfSmallRec, height* 23/ 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height *23/ 60 + halfSmallRec, piePaint);
 /**
 * 更改画笔颜色为小球颜色
 */
 piePaint.setColor(mSmallBallColor);
 /**
 * 绘制下边的小方块即小球的小方块
 */
 canvas.drawRect(width * 2 / 5 - halfSmallRec, height * 37 / 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height * 37 / 60 + halfSmallRec, piePaint);
 /**
 * 开始绘制文字,先设置文字颜色
 */
 textPaint.setColor(getResources().getColor(typedValue.resourceId));
 /**
 * 设置问题大小
 */
 textPaint.setTextSize(textSize);
 /**
 * 大球数量
 */
 String strBig = strBigBallName + mBigBallNumber;
 /**
 * 测量文字宽度
 */
 float textBigWidth =textPaint.measureText(strBig);
 Paint.FontMetrics fontMetrics=textPaint.getFontMetrics();
 /**
 * 绘制上边大球数量
 */
 canvas.drawText(strBig, width * 9 / 20 + textBigWidth / 2, height *23/ 60 - fontMetrics.top / 3, textPaint);
 /**
 * 小球数量
 */
 String strSmall = strSmallBallName + mSmallBallNumber;
 /**
 * 测量文字宽度
 */
 float textUnderWidth=textPaint.measureText(strSmall);
 /**
 * 绘制下边的小球数量
 */
 canvas.drawText(strSmall,width*9/20+textUnderWidth/2,height*37/60-fontMetrics.top/3,textPaint);
 /**
 * 更改画笔颜色,开始绘制百分比
 */
 textPaint.setColor(getResources().getColor(R.color.half_transparent));
 String strBigPercent =" ("+ mPercentBigBall +")";
 /**
 * 测量大球百分比文字宽度
 */
 float bigPercent =textPaint.measureText(strBigPercent);
 /**drawText(String text, float x, float y, Paint paint)
 * 绘制文字的API,四个参数分别是文字内容,起始绘制x坐标,起始绘制y坐标,画笔
 * 以为设置了居中绘制,因此穿进去的xy坐标为文字的中心点
 */
 canvas.drawText(strBigPercent, width * 9 / 20+ textBigWidth + bigPercent /2, height*23 / 60-fontMetrics.top*1/3, textPaint);
 /**
 * 同样的道理绘制小球的百分比
 */
 String strSmallPercent =" ("+ mPercentSmallBall +")";
 float smallPercent =textPaint.measureText(strSmallPercent);
 canvas.drawText(strSmallPercent,width*9/20+textUnderWidth+ smallPercent /2,height*37/60-fontMetrics.top/3,textPaint);
}

Canvas 绘制文本时,使用FontMetrics对象,计算位置的坐标。参考:使用FontMetrics对象计算位置坐标

Android自定义控件实现饼状图

设置文字绘制以中心为起点开始绘制

?
1
textPaint.setTextAlign(Paint.Align.CENTER);

x的坐标好计算,y坐标需要按需使用FontMetrics几个属性即可

完整代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
public class PieHalfView extends View {
 /**
 * 左边饼状图的画笔
 */
 private Paint piePaint;
 /**
 * 右边文字的画笔
 */
 private Paint textPaint;
 /**
 * 饼状图的半径
 */
 private float radius;
 private RectF rectf;
 /**
 * 饼状图中第一个扇形占整个圆的比例
 */
 private float percent;
 /**
 * 深浅两种颜色
 */
 private int mBigBallColor, mSmallBallColor;
 /**
 * 大小球的数量
 */
 private int mBigBallNumber;
 private int mSmallBallNumber;
 /**
 * 大小球所占的百分比
 */
 private String mPercentBigBall;
 private String mPercentSmallBall;
 /**
 * 动态获取属性
 */
 private TypedValue typedValue;
 /**
 * 中间的文字信息
 */
 private String strBigBallName;
 private String strSmallBallName;
 
 public PieHalfView(Context context) {
 super(context);
 init(context);
 }
 
 public PieHalfView(Context context, AttributeSet attrs) {
 super(context, attrs);
 init(context);
 }
 
 public PieHalfView(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 init(context);
 }
 private void init(Context context) {
 /**
 * 设置饼状图画笔
 */
 piePaint =new Paint();
 piePaint.setAntiAlias(true);
 piePaint.setStyle(Paint.Style.FILL);
 /**
 * 设置文字画笔
 */
 textPaint=new Paint();
 textPaint.setStyle(Paint.Style.STROKE);
 textPaint.setAntiAlias(true);
 textPaint.setTextAlign(Paint.Align.CENTER);
 /**
 * 下边设置一些默认的值,如果调用者没有传值进来的话,用这些默认值
 */
 mBigBallColor = 0xFF9CCA5D;
 mSmallBallColor =0xFF5F7048;
 /*TypedValue:Container for a dynamically typed data value. Primarily used with Resources for holding resource values.*/
 typedValue=new TypedValue();
 context.getTheme().resolveAttribute(R.attr.maintextclor,typedValue,true);
 mBigBallNumber =1;
 mSmallBallNumber =3;
 mPercentBigBall ="40%";
 mPercentSmallBall ="60%";
 strBigBallName =getResources().getString(R.string.big);
 strSmallBallName =getResources().getString(R.string.small);
 }
 
 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 /**
 * 饼状图的x坐标
 */
 float centreX= getWidth()/5;
 /**
 * 饼状图的y坐标
 */
 float centreY= getHeight()/2;
 /**
 * 文字的大小
 */
 float textSize=getHeight()/7;
 float width=(float)getWidth();
 float height=(float)getHeight();
 /**
 * 中间小正方形边长的一半
 */
 float halfSmallRec =((float)getHeight())*3/70;
 percent =((float) mBigBallNumber)/(mBigBallNumber + mSmallBallNumber);
 /**
 * 求饼状图的半径
 */
 radius= Math.min(getWidth() * 1 / 8, getHeight() * 10 / 35);
 /**
 * 构建一个正方形,饼状图是这个正方形的内切圆
 */
 rectf=new RectF((int)(centreX-radius),(int)(centreY-radius),(int)(centreX+radius),(int)(centreY+radius));
 /**
 * 设置饼状图画笔的颜色,先绘制大球占的比例
 */
 piePaint.setColor(mBigBallColor);
 /* The arc is drawn clockwise. An angle of 0 degrees correspond to the
 * geometric angle of 0 degrees (3 o'clock on a watch.)*/
 /* drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)*/
 /* 绘制大球的扇形图,float startAngle起始角度的0度的位置在3点钟方向
 * 因此大球的扇形图要从12点钟开始绘制,所以起始角度为270度*/
 canvas.drawArc(rectf, 270, 360 * percent, true, piePaint);
 /**
 * 换种颜色,开始绘制小球占的饼状图
 */
 piePaint.setColor(mSmallBallColor);
 /**
 * 起始角度就是12点钟加上360度乘以大球占的比例,12点钟转换为起始角度为270度
 */
 canvas.drawArc(rectf, 270 + 360 * percent, 360 - 360 * percent, true, piePaint);
 /**
 * 颜色更改为大球的颜色*/
  piePaint.setColor(mBigBallColor);
 /**
 * 绘制上边的小方块,也就是大球的方块
 */
 canvas.drawRect(width * 2 / 5 - halfSmallRec, height* 23/ 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height *23/ 60 + halfSmallRec, piePaint);
 /**
 * 更改画笔颜色为小球颜色
 */
 piePaint.setColor(mSmallBallColor);
 /**
 * 绘制下边的小方块即小球的小方块
 */
 canvas.drawRect(width * 2 / 5 - halfSmallRec, height * 37 / 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height * 37 / 60 + halfSmallRec, piePaint);
 /**
 * 开始绘制文字,先设置文字颜色
 */
 textPaint.setColor(getResources().getColor(typedValue.resourceId));
 /**
 * 设置问题大小
 */
 textPaint.setTextSize(textSize);
 /**
 * 大球数量
 */
 String strBig = strBigBallName + mBigBallNumber;
 /**
 * 测量文字宽度
 */
 float textBigWidth =textPaint.measureText(strBig);
 Paint.FontMetrics fontMetrics=textPaint.getFontMetrics();
 /**
 * 绘制上边大球数量
 */
 canvas.drawText(strBig, width * 9 / 20 + textBigWidth / 2, height *23/ 60 - fontMetrics.top / 3, textPaint);
 /**
 * 小球数量
 */
 String strSmall = strSmallBallName + mSmallBallNumber;
 /**
 * 测量文字宽度
 */
 float textUnderWidth=textPaint.measureText(strSmall);
 /**
 * 绘制下边的小球数量
 */
 canvas.drawText(strSmall,width*9/20+textUnderWidth/2,height*37/60-fontMetrics.top/3,textPaint);
 /**
 * 更改画笔颜色,开始绘制百分比
 */
 textPaint.setColor(getResources().getColor(R.color.half_transparent));
 String strBigPercent =" ("+ mPercentBigBall +")";
 /**
 * 测量大球百分比文字宽度*/
 float bigPercent =textPaint.measureText(strBigPercent);
 /** drawText(String text, float x, float y, Paint paint)
 * 绘制文字的API,四个参数分别是文字内容,起始绘制x坐标,起始绘制y坐标,画笔
 * 以为设置了居中绘制,因此穿进去的xy坐标为文字的中心点
 */
 canvas.drawText(strBigPercent, width * 9 / 20+ textBigWidth + bigPercent /2, height*23 / 60-fontMetrics.top*1/3, textPaint);
 /*
 * 同样的道理绘制小球的百分比
 */
 String strSmallPercent =" ("+ mPercentSmallBall +")";
 float smallPercent =textPaint.measureText(strSmallPercent);
 canvas.drawText(strSmallPercent,width*9/20+textUnderWidth+ smallPercent /2,height*37/60-fontMetrics.top/3,textPaint);
 }
 public void setPercent(float percent1){
 this.percent =percent1;
 invalidate();
 }
 public void setColor(int mBigBallColor,int mSmallBallColor){
 this.mBigBallColor =mBigBallColor;
 this.mSmallBallColor =mSmallBallColor;
 invalidate();
 }
 
 public void setOverRunner(String bigPecent, String smallPercent, int big, int small,
 int bigColor, int smallColor){
 this.mPercentBigBall = bigPecent;
 this.mPercentSmallBall = smallPercent;
 this.mBigBallNumber = big;
 this.mSmallBallNumber = small;
 this.mBigBallColor = bigColor;
 this.mSmallBallColor = smallColor;
 invalidate();
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/wangshihui512/article/details/51354502

延伸 · 阅读

精彩推荐
  • AndroidAndroid实现悬浮窗体效果

    Android实现悬浮窗体效果

    这篇文章主要为大家详细介绍了Android实现悬浮窗体效果,显示悬浮窗口,窗口可以拖动,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    叶超Luka8202022-08-30
  • AndroidKotlin超简单实现StepView的方法

    Kotlin超简单实现StepView的方法

    这篇文章主要介绍了Kotlin超简单实现StepView的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    joketng5742022-08-17
  • AndroidAndroid实现EditText添加下划线

    Android实现EditText添加下划线

    这篇文章主要为大家详细介绍了Android如何实现给EditText添加下划线,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    星辰之力4992022-07-24
  • AndroidAndroid仿微信群聊头像

    Android仿微信群聊头像

    这篇文章主要为大家介绍了Android仿微信群聊头像的相关资料,感兴趣的小伙伴们可以参考一下...

    Hankkin10082021-05-20
  • Androidandroid利用xml实现分割线

    android利用xml实现分割线

    这篇文章主要介绍了android利用xml实现分割线的方法,如何用xml产生一个分割线?感兴趣的小伙伴们可以参考一下...

    学习编程知识8002021-04-27
  • AndroidAndroid进阶之App启动流程和源码详解

    Android进阶之App启动流程和源码详解

    Android中有四大组件:Activity、Service、BroadcastReceiver、ContentProvider。我们最常接触也是用户直接感受到的就是Activity了,今天来就说说Android启动的执行过程和...

    Android开发编程12362021-08-10
  • Android浅析Android文件管理器(项目一)

    浅析Android文件管理器(项目一)

    这篇文章主要介绍了浅析Android文件管理器(一)的相关资料,需要的朋友可以参考下...

    Chenstyle12012021-04-09
  • AndroidAndroid应用中实现选择本地文件与目录的实例分享

    Android应用中实现选择本地文件与目录的实例分享

    这篇文章主要介绍了Android应用中实现选择本地文件与目录的实例分享,相当于从app内呼出的简易的资源管理器来使用本地资源,需要的朋友可以参考下...

    qinjuning9022021-06-21