Android自定义控件实现饼状图
时间:2022-07-28
本文章向大家介绍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对象计算位置坐标
设置文字绘制以中心为起点开始绘制
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();
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助。
- 扫雷游戏制作学习过程
- JavaWeb学习之环境搭建
- Java初学之华容道游戏
- java基础学习之 消息对话款
- 暑假集训之专题----拓扑排序题解
- 李沐:从头开始介绍机器学习,眼花缭乱的机器学习应用
- hdu------2488Tornado(几何)
- nyoj------203三国志
- nyoj 115------城市平乱( dijkstra // bellman )
- hdu----(1847)Good Luck in CET-4 Everybody!(简单巴什博奕)
- hdu----(3118)Arbiter(构造二分图)
- hdu----(1528)Card Game Cheater(最大匹配/贪心)
- hdu-----(1507)Uncle Tom's Inherited Land*(二分匹配)
- hdu----149850 years, 50 colors(最小覆盖点)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Kubernetes 通过statefulset部署redis cluster集群
- 猿实战13——实现你没听说过的前台类目
- 猿实战14——前台类目之广告牌设置
- 猿实战15——关联你所不明白的前后台类目
- 完美解决方案-雪花算法ID到前端之后精度丢失问题
- 猿实战16——承运商之搭建你的运费基石
- List对象去重及按属性去重的8种方法-java基础总结第六篇
- 总结java创建文件夹的4种方法及其优缺点-JAVA IO基础总结第三篇
- 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇
- 总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇
- 总结java中删除文件或文件夹的7种方法-JAVA IO基础总结第四篇
- 总结java中创建并写文件的五种方式-JAVA IO基础总结第一篇
- 8成以上的java线程状态图都画错了,看看这个-图解java并发第二篇
- 特殊数据格式处理-JSON框架Jackson精解第2篇
- 序列化与反序列化核心用法-JSON框架Jackson精解第一篇