Android自定义控件实现饼状图
程序员文章站
2022-04-30 22:41:51
本文实现一个如图所示的控件,包括两部分,左边的饼状图和中间的两个小方块,及右边的两行文字
实现起来比较简单,只是一些绘图api的调用
核心代码在ondraw函数里边...
本文实现一个如图所示的控件,包括两部分,左边的饼状图和中间的两个小方块,及右边的两行文字
实现起来比较简单,只是一些绘图api的调用
核心代码在ondraw函数里边,对静态控件进行绘制即可
@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对象计算位置坐标
设置文字绘制以中心为起点开始绘制
textpaint.settextalign(paint.align.center);
x的坐标好计算,y坐标需要按需使用fontmetrics几个属性即可
完整代码如下:
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(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 使用BigDecimal进行精确运算
下一篇: 大专生自学Java到找到高薪工作历程