当前位置: 移动技术网 > 移动技术>移动开发>Android > Android自定义控件实现饼状图

Android自定义控件实现饼状图

2019年07月30日  | 移动技术网移动技术  | 我要评论

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

实现起来比较简单,只是一些绘图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();
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网