欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义控件实现饼状图

程序员文章站 2022-04-30 22:41:51
本文实现一个如图所示的控件,包括两部分,左边的饼状图和中间的两个小方块,及右边的两行文字 实现起来比较简单,只是一些绘图api的调用 核心代码在ondraw函数里边...

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

Android自定义控件实现饼状图

实现起来比较简单,只是一些绘图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对象计算位置坐标

Android自定义控件实现饼状图

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

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();
 }
}

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