项目需要做一个android饼状图的效果 因为元素比较多 并且有些元素的百分比为0也需要显示出来,一开始考虑使用MPAndroidCharthttps://github.com/PhilJay/MPAndroidChart,毕竟点赞数量多 但是看了下效果 跟要求差别还是有点大,所以又找了个其他的项目参考PieChartViewhttps://github.com/luweibin3118/PieChartView, 这个项目 发现只能设置int类型的百分比 而且当条目过多的时候 会导致显示的文本覆盖重合之类的 所以改了两个地方

1.将int 类型改为float类型 百分比

2.将百分比显示由标注线下面移动到 content后面

下面贴下代码和效果

源代码可以去项目里面找  我只放下修改后的代码

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.Point;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
public class MyPieChartView extends View{private Paint mPaint;private Path mPath, drawLinePath = new Path();private PathMeasure mPathMeasure = new PathMeasure();private Canvas mCanvas;private int width, height;private RectF pieRectF, tempRectF;private int radius;private List<MyPieChartView.ItemType> itemTypeList, leftTypeList, rightTypeList;private List<Point> itemPoints;private int cell = 0;private float innerRadius = 0.0f;private float offRadius = 0, offLine;private int textAlpha;private Point firstPoint;private int backGroundColor = 0xffffffff;private int itemTextSize = 30, textPadding = 8;private int defaultStartAngle = -90;private float pieCell;private ValueAnimator animator;private long animDuration = 1000;private Point startPoint = new Point();private Point centerPoint = new Point();private Point endPoint = new Point();private Point tempPoint = new Point();public MyPieChartView(Context context) {super(context);init();}public MyPieChartView(Context context, AttributeSet attrs) {super(context, attrs);init();}private void init() {mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);mPath = new Path();pieRectF = new RectF();tempRectF = new RectF();itemTypeList = new ArrayList<>();leftTypeList = new ArrayList<>();rightTypeList = new ArrayList<>();itemPoints = new ArrayList<>();}@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();startAnim();}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();if (animator != null) {animator.cancel();}}private void startAnim() {animator = ValueAnimator.ofFloat(0, 360f * 2);animator.setDuration(animDuration);animator.setInterpolator(new LinearInterpolator());animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {float value = (float) animation.getAnimatedValue();if (value < 360f) {offRadius = value;offLine = 0;textAlpha = 0;} else if (value >= 360f) {offRadius = 360f;offLine = (value - 360f) / 360f;if (offLine > 0.5f) {textAlpha = (int) (255 * ((offLine - 0.5f) / 0.5f));if (textAlpha > 255) textAlpha = 255;} else {textAlpha = 0;}} else if (value == 360f * 2) {offRadius = 360f;offLine = 1.0f;textAlpha = 255;}postInvalidate();}});animator.start();}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);this.width = w;this.height = h;radius = Math.min(width, height) / 4;pieRectF.set(width / 2 - radius, height / 2 - radius, width / 2 + radius, height / 2 + radius);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);try {mCanvas = canvas;drawPie();if (offRadius == 360f) {drawTitle();}} catch (Exception e) {e.printStackTrace();}}private void drawTitle() {resetPaint();float startRadius = defaultStartAngle;int count = rightTypeList.size();int h;if (count > 1) {h = (radius * 2) / (count - 1);} else {h = radius;}for (int i = 0; i < count; i++) {mPath.reset();MyPieChartView.ItemType itemType = rightTypeList.get(i);double angle = 2 * Math.PI * ((startRadius + itemType.radius / 2) / 360d);int x = (int) (width / 2 + radius * Math.cos(angle));int y = (int) (height / 2 + radius * Math.sin(angle));startPoint.set(x, y);centerPoint.set((int) (width / 2 + radius * 1.2f), height / 2 - radius + h * (i));endPoint.set((int) (width * 0.98f), centerPoint.y);mPath.moveTo(startPoint.x, startPoint.y);mPath.lineTo(centerPoint.x, centerPoint.y);mPath.lineTo(endPoint.x, endPoint.y);resetPaint();mPaint.setStrokeWidth(2);mPaint.setColor(itemType.color);mPaint.setStyle(Paint.Style.STROKE);mPathMeasure.setPath(mPath, false);drawLinePath.reset();mPathMeasure.getSegment(0, mPathMeasure.getLength() * offLine, drawLinePath, true);mCanvas.drawPath(drawLinePath, mPaint);startRadius += itemType.radius;if (textAlpha > 0) {mPaint.setTextSize(itemTextSize);mPaint.setStyle(Paint.Style.FILL);mPaint.setTextAlign(Paint.Align.CENTER);mPaint.setAlpha(textAlpha);mCanvas.drawText(itemType.type+itemType.getPercent(), centerPoint.x + (endPoint.x - centerPoint.x) / 2,centerPoint.y - textPadding, mPaint);mPaint.setTextSize(itemTextSize * 4 / 5);
//                mCanvas.drawText(itemType.getPercent(), centerPoint.x + (endPoint.x - centerPoint.x) / 2,
//                        centerPoint.y + (itemTextSize + textPadding) * 4 / 5, mPaint);  //itemType.getPercent()移动到itemType.type后面了}}count = leftTypeList.size();if (count > 1) {h = (radius * 2) / (count - 1);} else {h = radius;}for (int i = 0; i < count; i++) {mPath.reset();MyPieChartView.ItemType itemType = leftTypeList.get(i);double angle = 2 * Math.PI * ((startRadius + itemType.radius / 2) / 360d);int x = (int) (width / 2 + radius * Math.cos(angle));int y = (int) (height / 2 + radius * Math.sin(angle));startPoint.set(x, y);centerPoint.set((int) (width / 2 - radius * 1.2f), height / 2 - radius + h * (count - 1 - i));endPoint.set((int) (width * 0.02f), centerPoint.y);mPath.moveTo(startPoint.x, startPoint.y);mPath.lineTo(centerPoint.x, centerPoint.y);mPath.lineTo(endPoint.x, endPoint.y);resetPaint();mPaint.setStrokeWidth(2);mPaint.setColor(itemType.color);mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setStyle(Paint.Style.STROKE);mPathMeasure.setPath(mPath, false);drawLinePath.reset();mPathMeasure.getSegment(0, mPathMeasure.getLength() * offLine, drawLinePath, true);mCanvas.drawPath(drawLinePath, mPaint);startRadius += itemType.radius;if (textAlpha > 0) {mPaint.setTextSize(itemTextSize);mPaint.setStyle(Paint.Style.FILL);mPaint.setTextAlign(Paint.Align.CENTER);mPaint.setAlpha(textAlpha);mCanvas.drawText(itemType.type+itemType.getPercent(), centerPoint.x + (endPoint.x - centerPoint.x) / 2,centerPoint.y - textPadding, mPaint);mPaint.setTextSize(itemTextSize * 4 / 5);
//                mCanvas.drawText(itemType.getPercent(), centerPoint.x + (endPoint.x - centerPoint.x) / 2,
//                        centerPoint.y + (itemTextSize + textPadding) * 4 / 5, mPaint);}}if (textAlpha == 1f) {itemTypeList.clear();leftTypeList.clear();rightTypeList.clear();itemPoints.clear();}}private void drawPie() {if (mCanvas == null) {return;}mCanvas.drawColor(backGroundColor);mPaint.setStyle(Paint.Style.FILL);float sum = 0;for (MyPieChartView.ItemType itemType : itemTypeList) {sum += itemType.widget;}float a = 360f / sum;float startRadius = defaultStartAngle;float sumRadius = 0;leftTypeList.clear();rightTypeList.clear();itemPoints.clear();for (MyPieChartView.ItemType itemType : itemTypeList) {itemType.radius = itemType.widget * a;double al = 2 * Math.PI * ((startRadius + 90) / 360d);tempPoint.set((int) (width / 2 + radius * Math.sin(al)),(int) (height / 2 - radius * Math.cos(al)));if (cell > 0) {if (startRadius == defaultStartAngle) {firstPoint = tempPoint;}}double angle = 2 * Math.PI * ((startRadius + itemType.radius / 2) / 360d);double sin = -Math.sin(angle);double cos = -Math.cos(angle);if (cos > 0) {leftTypeList.add(itemType);} else {rightTypeList.add(itemType);}sumRadius += Math.abs(itemType.radius);mPaint.setStyle(Paint.Style.FILL);mPaint.setColor(itemType.color);if (pieCell > 0) {if (sumRadius <= offRadius) {tempRectF.set(pieRectF.left - (float) (pieCell * cos), pieRectF.top - (float) (pieCell * sin),pieRectF.right - (float) (pieCell * cos), pieRectF.bottom - (float) (pieCell * sin));mCanvas.drawArc(tempRectF, startRadius, itemType.radius, true, mPaint);} else {mCanvas.drawArc(tempRectF, startRadius, itemType.radius - (Math.abs(offRadius - sumRadius)), true, mPaint);break;}} else {if (sumRadius <= offRadius) {mCanvas.drawArc(pieRectF, startRadius, itemType.radius, true, mPaint);} else {mCanvas.drawArc(pieRectF, startRadius, itemType.radius - (Math.abs(offRadius - sumRadius)), true, mPaint);break;}}startRadius += itemType.radius;if (cell > 0 && pieCell == 0) {mPaint.setColor(backGroundColor);mPaint.setStrokeWidth(cell);mCanvas.drawLine(getWidth() / 2, getHeight() / 2, tempPoint.x, tempPoint.y, mPaint);}}if (cell > 0 && firstPoint != null && pieCell == 0) {mPaint.setColor(backGroundColor);mPaint.setStrokeWidth(cell);mCanvas.drawLine(getWidth() / 2, getHeight() / 2, firstPoint.x, firstPoint.y, mPaint);}mPaint.setStyle(Paint.Style.FILL);mPaint.setColor(backGroundColor);if (innerRadius > 0 && pieCell == 0) {mCanvas.drawCircle(width / 2, height / 2, radius * innerRadius, mPaint);}}public void resetPaint() {mPaint.reset();mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setAlpha(255);}/*** 添加一条分类数据** @param itemType*/public void addItemType(MyPieChartView.ItemType itemType) {if (itemTypeList != null) {itemTypeList.add(itemType);}}/*** 设置每条图之间的间歇大小** @param cell*/public void setCell(int cell) {this.cell = cell;}/*** 设置内部圆的半径比例,eg:0.5f** @param innerRadius*/public void setInnerRadius(float innerRadius) {if (innerRadius > 1.0f) {innerRadius = 1.0f;} else if (innerRadius < 0) {innerRadius = 0;}this.innerRadius = innerRadius;}/*** 设置背景颜色** @param backGroundColor*/public void setBackGroundColor(int backGroundColor) {this.backGroundColor = backGroundColor;}/*** 设置每条字体大小** @param itemTextSize*/public void setItemTextSize(int itemTextSize) {this.itemTextSize = itemTextSize;}/*** 设置字体距离横线的padding值** @param textPadding*/public void setTextPadding(int textPadding) {this.textPadding = textPadding;}/*** 设置动画时间** @param animDuration*/public void setAnimDuration(long animDuration) {this.animDuration = animDuration;}/*** 代替方法{@link #setCell(int)}** @param pieCell*/@Deprecatedpublic void setPieCell(int pieCell) {this.cell = pieCell;}public static class ItemType {private static final DecimalFormat df = new DecimalFormat("0.0%");String type;float widget;int color;float radius;public ItemType(String type, float widget, int color) {this.type = type;this.widget = widget;this.color = color;}public String getPercent() {return df.format(radius / 360f);}}
}

布局文件:

   <com.runjiang.cityplatform.widget.MyPieChartViewandroid:id="@+id/piechart"android:layout_width="match_parent"android:layout_height="300dp"/>

使用方法很简单:

pieChartView.addItemType(new PieChartView.ItemType("小米", 13, 0xff8B5A00));

Android饼状图相关推荐

  1. android饼状图简书,自定义 view 练手 - 简单的饼状图

    今天咱们来一个例子练练手,饼状图这样的图表算是最好的了,复杂的话可以很复杂, 采用 surfaceview + 动画 可以使用很优秀的观感体验:简单的话可以很简单,仅仅画出图来就行,不用考虑动画啥的 ...

  2. android饼状图简书,Charts-饼状图

    上篇文章已经讲述了折线图的用法这边文章主要来谈饼状图. 其实Charts难的部分主要在于配置,所以同样主要说说他的配置. pieGraphView.setExtraOffsets(left: 10, ...

  3. android 中空饼图控件,android饼状图内是空心的怎么做

    满意答案 先定义一个GraphicalView GraphicalView graphicalView; 然后,从chartfactory获取 graphicalView=ChartFactory.g ...

  4. android带动画的饼图,Android部分源码资源共享(视屏转GIF图片工具、仿抖音、仿朋友圈、仿红包、饼状图、引导图,图灵源码等)...

    视屏转为gif图片工具: 下载地址:CSDN 下载 1.封装了各项工具类,例如,日志,打印,缓存等,可直接使用项目 百度网盘:下载    提取码:fq07 2.Android高仿抖音 1.项目 的bu ...

  5. android 第三方扇形图,Android扇形图(饼状图)

    关于Android的图形控件,市场上是有很多的开源库的 我个人用的比较多的就是:MPAndroidChart,个人感觉挺好用的,但是有写时候,满足不了需求,就需要自己去写了. 先看看我们的效果图: T ...

  6. android 自定义饼图半径不定,【Android】仿支付宝账单统计饼状图的自定义view

    仿支付宝统计饼状图的自定义view,如下图: 项目地址:https://github.com/bigeyechou/CustomViewCollection 目录:customviewcollecti ...

  7. android 最简单的饼状图

    录制的gif图有点渣,但是实际效果还是可以的. 因为项目需要绘制饼状图,就很简单的饼状图带一个选中的效果,本来也想使用MPAndroidChart这个库的,但是觉得就实现一个效果引用整个库,对于一个有 ...

  8. Android自定义饼状图

    1.啥都别说,先上效果图. 2.这效果是平时真实项目开发可能用到的.我也是看到Android交流群里有人要这种效果,于是开始动手写一写. 3.分析:这个自定义View效果 的实现大概分为几步 3.1. ...

  9. Android部分源码资源共享(视屏转GIF图片工具、仿抖音、仿朋友圈、仿红包、饼状图、引导图,图灵源码等)

    视屏转为gif图片工具: 下载地址:CSDN 下载 1.封装了各项工具类,例如,日志,打印,缓存等,可直接使用项目 百度网盘:下载     提取码:fq07 2.Android高仿抖音 1.项目 的b ...

最新文章

  1. spring框架搭建第二天
  2. 【博客话题】技术生涯中的出与入
  3. 【今晚七点半】:对话平行未来姜雨晴——重启熊猫直播背后的故事
  4. 玩转oracle 11g(32):plsql版本低需到配置文件中添加配置
  5. Oracle存储过程中使用游标来批量解析CLOB字段里面的xml字符串:
  6. oracle告警日志备份,教你怎样用Oracle方便地查看报警日志错误
  7. MyCat分布式数据库集群架构工作笔记0013---高可用_Mycat双主双从复制配置上
  8. Qt 学习笔记(5)绘图 五子棋游戏
  9. 问题 A: 编写函数:比较三个数大小 (Append Code)
  10. MVC系统的Filter
  11. 微信公众平台开发(一) 配置接口
  12. python config文件_Python如何配置config文件?
  13. Mbed TLS 编码规范
  14. 北大青鸟昌平校区 | 学网络运维与安全就业薪资多少?
  15. python操作格林威治时间
  16. Bootstrap3基础 img-rounded 图片的四个角改成圆角
  17. Dell R910报错E1234的处理方法
  18. 戴尔灵越系列服务器是什么,戴尔灵越系列哪个好-2021戴尔灵越系列型号选购推荐...
  19. Linux Shell重定向 管道命令 grep搜索 awk编程 sed文件操作高阶函数
  20. python实现去除图片纯色边框和给图片补边

热门文章

  1. C语言 共享单车管理系统(读取、写入、删除文件中数据)
  2. 提高效率和质量——生产车间6S管理
  3. 23种设计模式-行为型模式-访问者模式
  4. 如何用手机拍出好看的照片(简单易操作,暖男必备)
  5. 【论文分享】SMOKE: Scalable Path-Sensitive Memory Leak Detection for Millions of Lines of Code
  6. 阿波龙发布一周年,百度无人驾驶从“开放”走向 “共赢”
  7. 在线答题APP动工前的小总结
  8. 第五课 511遇见易语言大漠找字FindStrE FindStrFastE系列
  9. visual studo 2022中使用Opencv人脸检测
  10. 推荐几个app开源项目