Android编程实现canvas绘制饼状统计图功能示例【自动适应条目数量与大小】
发布时间 - 2026-01-10 22:48:17 点击率:次本文实例讲述了Android编程实现canvas绘制饼状统计图功能。分享给大家供大家参考,具体如下:

本例的目的是实现一个简单的饼状统计图,效果如下:
特点:
1.使用非常方便,可放在xml布局文件中,然后在代码中设置内容,即:
PieChartView pieChartView = (PieChartView) findViewById(R.id.pie_chart);
PieChartView.PieItemBean[] items = new PieChartView.PieItemBean[]{
new PieChartView.PieItemBean("娱乐", 200),
new PieChartView.PieItemBean("旅行", 100),
new PieChartView.PieItemBean("学习", 120),
new PieChartView.PieItemBean("人际关系", 160),
new PieChartView.PieItemBean("交通", 100),
new PieChartView.PieItemBean("餐饮", 480)
};
pieChartView.setPieItems(items);
2.条目数量,大小及折线位置,长度均自适应。左侧条目往左侧划线,右侧条目往右侧划线,文字描述与百分比居中对齐,并且文字“下划线”与文字长度自适应。对于很小的条目,将自动将折线延长以尽可能避免文字遮盖
核心代码:PieChartView.Java:
public class PieChartView extends View {
private int screenW, screenH;
/**
* The paint to draw text, pie and line.
*/
private Paint textPaint, piePaint, linePaint;
/**
* The center and the radius of the pie.
*/
private int pieCenterX, pieCenterY, pieRadius;
/**
* The oval to draw the oval in.
*/
private RectF pieOval;
private float smallMargin;
private int[] mPieColors = new int[]{Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.MAGENTA, Color.CYAN};
private PieItemBean[] mPieItems;
private float totalValue;
public PieChartView(Context context) {
super(context);
init(context);
}
public PieChartView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PieChartView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
//init screen
screenW = ScreenUtils.getScreenW(context);
screenH = ScreenUtils.getScreenH(context);
pieCenterX = screenW / 2;
pieCenterY = screenH / 3;
pieRadius = screenW / 4;
smallMargin = ScreenUtils.dp2px(context, 5);
pieOval = new RectF();
pieOval.left = pieCenterX - pieRadius;
pieOval.top = pieCenterY - pieRadius;
pieOval.right = pieCenterX + pieRadius;
pieOval.bottom = pieCenterY + pieRadius;
//The paint to draw text.
textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setTextSize(ScreenUtils.dp2px(context, 16));
//The paint to draw circle.
piePaint = new Paint();
piePaint.setAntiAlias(true);
piePaint.setStyle(Paint.Style.FILL);
//The paint to draw line to show the concrete text
linePaint = new Paint();
linePaint.setAntiAlias(true);
linePaint.setStrokeWidth(ScreenUtils.dp2px(context, 1));
}
//The degree position of the last item arc's center.
private float lastDegree = 0;
//The count of the continues 'small' item.
private int addTimes = 0;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mPieItems != null && mPieItems.length > 0) {
float start = 0.0f;
for (int i = 0; i < mPieItems.length; i++) {
//draw pie
piePaint.setColor(mPieColors[i % mPieColors.length]);
float sweep = mPieItems[i].getItemValue() / totalValue * 360;
canvas.drawArc(pieOval, start, sweep, true, piePaint);
//draw line away from the pie
float radians = (float) ((start + sweep / 2) / 180 * Math.PI);
float lineStartX = pieCenterX + pieRadius * 0.7f * (float) (Math.cos(radians));
float lineStartY = pieCenterY + pieRadius * 0.7f * (float) (Math.sin(radians));
float lineStopX, lineStopY;
float rate;
if (getOffset(start + sweep / 2) > 60) {
rate = 1.3f;
} else if (getOffset(start + sweep / 2) > 30) {
rate = 1.2f;
} else {
rate = 1.1f;
}
//If the item is very small, make the text further away from the pie to avoid being hided by other text.
if (start + sweep / 2 - lastDegree < 30) {
addTimes++;
rate += 0.2f * addTimes;
} else {
addTimes = 0;
}
lineStopX = pieCenterX + pieRadius * rate * (float) (Math.cos(radians));
lineStopY = pieCenterY + pieRadius * rate * (float) (Math.sin(radians));
canvas.drawLine(lineStartX, lineStartY, lineStopX, lineStopY, linePaint);
//write text
String itemTypeText = mPieItems[i].getItemType();
String itemPercentText = Utility.formatFloat(mPieItems[i].getItemValue() / totalValue * 100) + "%";
float itemTypeTextLen = textPaint.measureText(itemTypeText);
float itemPercentTextLen = textPaint.measureText(itemPercentText);
float lineTextWidth = Math.max(itemTypeTextLen, itemPercentTextLen);
float textStartX = lineStopX;
float textStartY = lineStopY - smallMargin;
float percentStartX = lineStopX;
float percentStartY = lineStopY + textPaint.getTextSize();
if (lineStartX > pieCenterX) {
textStartX += (smallMargin + Math.abs(itemTypeTextLen - lineTextWidth) / 2);
percentStartX += (smallMargin + Math.abs(itemPercentTextLen - lineTextWidth) / 2);
} else {
textStartX -= (smallMargin + lineTextWidth - Math.abs(itemTypeTextLen - lineTextWidth) / 2);
percentStartX -= (smallMargin + lineTextWidth - Math.abs(itemPercentTextLen - lineTextWidth) / 2);
}
canvas.drawText(itemTypeText, textStartX, textStartY, textPaint);
//draw percent text
canvas.drawText(itemPercentText, percentStartX, percentStartY, textPaint);
//draw text underline
float textLineStopX = lineStopX;
if (lineStartX > pieCenterX) {
textLineStopX += (lineTextWidth + smallMargin * 2);
} else {
textLineStopX -= (lineTextWidth + smallMargin * 2);
}
canvas.drawLine(lineStopX, lineStopY, textLineStopX, lineStopY, linePaint);
lastDegree = start + sweep / 2;
start += sweep;
}
}
}
public PieItemBean[] getPieItems() {
return mPieItems;
}
public void setPieItems(PieItemBean[] pieItems) {
this.mPieItems = pieItems;
totalValue = 0;
for (PieItemBean item : mPieItems) {
totalValue += item.getItemValue();
}
invalidate();
}
private float getOffset(float radius) {
int a = (int) (radius % 360 / 90);
switch (a) {
case 0:
return radius;
case 1:
return 180 - radius;
case 2:
return radius - 180;
case 3:
return 360 - radius;
}
return radius;
}
static class PieItemBean {
private String itemType;
private float itemValue;
PieItemBean(String itemType, float itemValue) {
this.itemType = itemType;
this.itemValue = itemValue;
}
public String getItemType() {
return itemType;
}
public void setItemType(String itemType) {
this.itemType = itemType;
}
public float getItemValue() {
return itemValue;
}
public void setItemValue(float itemValue) {
this.itemValue = itemValue;
}
}
}
完整实例代码点击此处本站下载。
更多关于Android相关内容感兴趣的读者可查看本站专题:《Android图形与图像处理技巧总结》、《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》
希望本文所述对大家Android程序设计有所帮助。
# Android
# canvas
# 绘制
# 饼状
# 统计图
# Android中使用Canvas绘制南丁格尔玫瑰图(Nightingale rose diagram
# Android编程之canvas绘制各种图形(点
# 直线
# 弧
# 圆
# 椭圆
# 文字
# 矩形
# 多边形
# 曲线
# 圆角矩形)
# Android编程开发之在Canvas中利用Path绘制基本图形(圆形
# 三角形等)
# Android使用Canvas绘制圆形进度条效果
# Android编程实现canvas绘制柱状统计图功能【自动计算宽高及分度值、可左右滑动】
# Android开发使用自定义View将圆角矩形绘制在Canvas上的方法
# Android 使用Canvas在图片上绘制文字的方法
# Android Canvas绘制文字横纵向对齐
# 自适应
# 进阶
# 放在
# 相关内容
# 下划线
# 感兴趣
# 给大家
# 点击此处
# 更多关于
# 解决方法
# 所述
# 图像处理
# 程序设计
# 往右
# 往左
# 本例
# 讲述了
# 目的是
# float
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
网站制作大概要多少钱一个,做一个平台网站大概多少钱?
如何在万网自助建站平台快速创建网站?
Laravel怎么在Blade中安全地输出原始HTML内容
微信小程序 wx.uploadFile无法上传解决办法
如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)
长沙做网站要多少钱,长沙国安网络怎么样?
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
如何快速搭建安全的FTP站点?
如何在IIS中配置站点IP、端口及主机头?
青岛网站建设如何选择本地服务器?
Laravel如何使用Service Provider服务提供者_Laravel依赖注入与容器绑定【深度】
Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程
北京企业网站设计制作公司,北京铁路集团官方网站?
如何快速查询域名建站关键信息?
如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?
Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制
网站制作软件免费下载安装,有哪些免费下载的软件网站?
Win11怎么关闭透明效果_Windows11辅助功能视觉效果设置
Laravel如何实现API资源集合?(Resource Collection教程)
html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】
什么是javascript作用域_全局和局部作用域有什么区别?
高防服务器:AI智能防御DDoS攻击与数据安全保障
谷歌Google入口永久地址_Google搜索引擎官网首页永久入口
成都网站制作公司哪家好,四川省职工服务网是做什么用?
C++用Dijkstra(迪杰斯特拉)算法求最短路径
东莞市网站制作公司有哪些,东莞找工作用什么网站好?
如何快速搭建高效香港服务器网站?
如何在景安云服务器上绑定域名并配置虚拟主机?
如何选择PHP开源工具快速搭建网站?
高防服务器租用如何选择配置与防御等级?
消息称 OpenAI 正研发的神秘硬件设备或为智能笔,富士康代工
如何使用 jQuery 正确渲染 Instagram 风格的标签列表
5种Android数据存储方式汇总
敲碗10年!Mac系列传将迎来「触控与联网」双革新
Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】
如何用虚拟主机快速搭建网站?详细步骤解析
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法
浅谈redis在项目中的应用
大型企业网站制作流程,做网站需要注册公司吗?
如何快速建站并高效导出源代码?
高端企业智能建站程序:SEO优化与响应式模板定制开发
黑客如何利用漏洞与弱口令入侵网站服务器?
Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives
高防服务器如何保障网站安全无虞?
Win11搜索栏无法输入_解决Win11开始菜单搜索没反应问题【技巧】
阿里云高弹*务器配置方案|支持分布式架构与多节点部署
千库网官网入口推荐 千库网设计创意平台入口
佛山企业网站制作公司有哪些,沟通100网上服务官网?
简历没回改:利用AI润色让你的文字更专业

