【Android开发日记】AndroidCharts 饼状图 PieView修改:添加数值和颜色
来源:互联网 发布:淘宝店铺开店日期 编辑:程序博客网 时间:2024/05/18 20:13
前言:前段时间做的工程,自己一个人小打小闹的修改着,代码不完善之处请在评论指出,谢谢!
工程来源:github AndroidCharts:https://github.com/dacer/AndroidCharts
修改:使得PieView可以显示数字和颜色
我的需求:将每间教室的名称显示在图上,同时根据数值 按比例涂色
效果图:
代码1:PieView修改后的代码:
package com.androidcharts;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Point;import android.graphics.Rect;import android.graphics.RectF;import android.util.AttributeSet;import android.util.Log;import android.view.View;import java.util.ArrayList;/** * Created by Dacer on 11/13/13. */public class PieView extends View { private Paint textPaint; private Paint redPaint; private Paint linePaint; private Paint whitePaint; private int mViewWidth; private int mViewHeight; private int textSize; private int pieRadius; private Point pieCenterPoint; private Point tempPoint; private Point tempPointRight; private int lineLength; private float leftTextWidth; private float rightTextWidth; private float topTextHeight; private int lineThickness; private RectF cirRect; private Rect textRect; private ArrayList<String> areanameList; private ArrayList<PieHelper> pieArrayList = new ArrayList<PieHelper>(); private ArrayList<PieHelper> pieArrayList_ = new ArrayList<PieHelper>(); //单纯备份传进的角度 private final int TEXT_COLOR = Color.parseColor("#9B9A9B"); private final int GRAY_COLOR = Color.parseColor("#D4D3D4"); private final int RED_COLOR = Color.argb(50, 255, 0, 51); private String[] colorArray = {"#e74c3c","#2980b9","#1abc9c"}; private Runnable animator = new Runnable() { @Override public void run() { boolean needNewFrame = false; for(PieHelper pie : pieArrayList){ pie.update(); if(!pie.isAtRest()){ needNewFrame = true; } } if (needNewFrame) { postDelayed(this, 10); } invalidate(); } }; public PieView(Context context){ this(context,null); } public PieView(Context context, AttributeSet attrs){ super(context, attrs); textSize = MyUtils.sp2px(context, 15); lineThickness = MyUtils.dip2px(context, 1); lineLength = MyUtils.dip2px(context, 10); textPaint = new Paint(); textPaint.setAntiAlias(true); textPaint.setColor(TEXT_COLOR); textPaint.setTextSize(textSize); textPaint.setTextAlign(Paint.Align.CENTER); Paint.FontMetrics fm = new Paint.FontMetrics(); textPaint.getFontMetrics(fm); textRect = new Rect(); textPaint.getTextBounds("18",0,1,textRect); redPaint = new Paint(textPaint); redPaint.setColor(RED_COLOR); linePaint = new Paint(textPaint); linePaint.setColor(GRAY_COLOR); linePaint.setStrokeWidth(lineThickness); whitePaint = new Paint(linePaint); whitePaint.setColor(Color.WHITE); tempPoint = new Point(); pieCenterPoint = new Point(); tempPointRight = new Point(); cirRect = new RectF(); leftTextWidth = textPaint.measureText("18"); rightTextWidth = textPaint.measureText("6"); topTextHeight = textRect.height(); } //传进画图需要的数据 public void setDate(ArrayList<PieHelper> helperList){ if(helperList != null && !helperList.isEmpty()){ this.pieArrayList_ = helperList; int pieSize = pieArrayList.isEmpty()? 0:pieArrayList.size(); for(int i=0;i<helperList.size();i++){ if(i>pieSize-1){// float mStart = helperList.get(i).getStart(); pieArrayList.add(new PieHelper(0,0,helperList.get(i))); }else{ pieArrayList.set(i, pieArrayList.get(i).setTarget(helperList.get(i))); } } int temp = pieArrayList.size() - helperList.size(); for(int i=0; i<temp; i++){ pieArrayList.remove(pieArrayList.size()-1); } }else { pieArrayList.clear(); } removeCallbacks(animator); post(animator); } //传进要画在图上的数据 public void setareanameList(ArrayList<String> AreaNameList){ this.areanameList = AreaNameList; } @Override protected void onDraw(Canvas canvas) { drawBackground(canvas); if(pieArrayList != null){ //涂色 for(int k=0; k<pieArrayList.size(); k++){ redPaint.setColor(Color.parseColor(colorArray[k%3])); canvas.drawArc(cirRect,pieArrayList.get(k).getStart(),pieArrayList.get(k).getSweep(),true,redPaint); } //画数据 for(int k=0; k< pieArrayList_.size(); k++){ //angle:12点方向起始,顺时针的角度 double angle = pieArrayList_.get(k).getStart()-270+pieArrayList_.get(k).getSweep()/2; //90-angle: 360-(angle-90) 转化成平面坐标系中角度,3点起始,逆时针 float x = (float) (pieCenterPoint.x+Math.cos(Math.toRadians(90-angle))*pieRadius*0.8); float y = (float) (pieCenterPoint.y-Math.sin(Math.toRadians(90-angle))*pieRadius*0.8); canvas.drawText(areanameList.get(k),x, y, textPaint); } } } //背景,主要是外圈圆 private void drawBackground(Canvas canvas){ //外圈白 //canvas.drawCircle(pieCenterPoint.x,pieCenterPoint.y,pieRadius+lineLength/2, whitePaint); //圆 canvas.drawCircle(pieCenterPoint.x,pieCenterPoint.y,pieRadius+lineThickness,linePaint); //内圈白 canvas.drawCircle(pieCenterPoint.x,pieCenterPoint.y,pieRadius,whitePaint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mViewWidth = measureWidth(widthMeasureSpec); mViewHeight = measureHeight(heightMeasureSpec); pieRadius = mViewWidth*5/12-lineLength*2-(int)(textPaint.measureText("18")/2); pieCenterPoint.set(mViewWidth/2-(int)rightTextWidth/2+(int)leftTextWidth/2, mViewHeight/2+textSize/2-(int)(textPaint.measureText("18")/2)); cirRect.set(pieCenterPoint.x-pieRadius, pieCenterPoint.y-pieRadius, pieCenterPoint.x+pieRadius, pieCenterPoint.y+pieRadius); setMeasuredDimension(mViewWidth, mViewHeight); } private int measureWidth(int measureSpec){ int preferred = 3; return getMeasurement(measureSpec, preferred); } private int measureHeight(int measureSpec){ int preferred = mViewWidth; return getMeasurement(measureSpec, preferred); } private int getMeasurement(int measureSpec, int preferred){ int specSize = View.MeasureSpec.getSize(measureSpec); int measurement; switch(View.MeasureSpec.getMode(measureSpec)){ case View.MeasureSpec.EXACTLY: measurement = specSize; break; case View.MeasureSpec.AT_MOST: measurement = Math.min(preferred, specSize); break; default: measurement = preferred; break; } return measurement; }}
代码2:实例化PieView,传递数据
final PieView pieView = (PieView)this.findViewById(R.id.pie_view);
Setpie(pieView);
private void Setpie(PieView pieView){ ArrayList<PieHelper> pieHelperArrayList = new ArrayList<PieHelper>(); int SHour =0; int SMin =0; int EHour =0; int EMin =0; int degree =0; int degreenew =0; int r = dataList.length; for (int i=0; i<r/3; i++){ Log.e("totalblanknum", "=" + totalblanknum); Log.e("dataList[1+i*3]", "=" + dataList[1+i*3]); degree = Integer.parseInt(dataList[1+i*3])*360/totalblanknum ; Log.e("degree", "=" + degree); degreenew = degree+ degreenew; Log.e("degreenew", "=" + degreenew); EHour = degreenew/30; EMin = degreenew%30*2; if(i+1 == r/3) { EHour = 12; EMin = 0; } //Log.e("EHour", "=" + EHour); //Log.e("EMin", "=" + EMin); pieHelperArrayList.add(new PieHelper(SHour,SMin,EHour,EMin)); SHour =EHour; SMin =EMin; } pieView.setareanameList(bottomList); //传进area名称 pieView.setDate(pieHelperArrayList); }
说明:
1.dataList数组是一个 字符串数组,数据结构:name1,blanknum1,totalnum1,name2,blanknum2,totalnum2,,,(参考上篇文章BarView的修改)
这里根据blanknum1,blanknum2,blanknum3...来确定PieView的比例,将name1,name2,name3...绘制在图上对应扇区
2.totalblanknum是 数据的总和,因为这个pieview是我界面的一部分,这个值在之前已经求出,就是相加:
for (int i=0; i<r/3; i++) totalblanknum = totalblanknum + Integer.parseInt(dataList[1+i*3]);
3.PieHelper 是AndroidCharts中的一个数据类型,因为话扇形需要知道 起始角度和终止角度 以及方向坐标轴等,因此原作者自定义了一个数据类型
现将PieHelper.java贴出:
package com.androidcharts;/** * Created by Dacer on 11/14/13. */public class PieHelper { private float start; private float end; private float targetStart; private float targetEnd; int velocity = 5; public PieHelper(float startDegree, float endDegree, PieHelper targetPie){ start = startDegree; end = endDegree; targetStart = targetPie.getStart(); targetEnd = targetPie.getEnd(); } public PieHelper(int startHour,int startMin,int endHour,int endMin){ start = 270+startHour*30+startMin*30/60; end = 270+endHour*30+endMin*30/60; while(end<start){ end+=360; } } public PieHelper(int startHour,int startMin,int startSec,int endHour,int endMin,int endSec){ start = 270+startHour*15+startMin*15/60+startSec*15/3600; end = 270+endHour*15+endMin*15/60+endSec*15/3600; while(end<start){ end+=360; } } PieHelper setTarget(float targetStart,float targetEnd){ this.targetStart = targetStart; this.targetEnd = targetEnd; return this; } PieHelper setTarget(PieHelper targetPie){ targetStart = targetPie.getStart(); targetEnd = targetPie.getEnd(); return this; } boolean isAtRest(){ return (start==targetStart)&&(end==targetEnd); } void update(){ start = updateSelf(start, targetStart, velocity); end = updateSelf(end, targetEnd, velocity); } public float getSweep(){ return end-start; } public float getStart(){ return start; } public float getEnd(){ return end; } private float updateSelf(float origin, float target, int velocity){ if (origin < target) { origin += velocity; } else if (origin > target){ origin-= velocity; } if(Math.abs(target-origin)<velocity){ origin = target; } return origin; }}说明:
1. 每一个PieHelper数据包括四个参数:
new PieHelper(SHour,SMin,EHour,EMin)
起始小时,起始分钟,终止小时,终止分钟 来确定一个扇区,12小时计时法
2. 根据数据得到起始角度:
首先根据某个数据占总数的比例得到degree,即扇形圆心角:degree = Integer.parseInt(dataList[1+i*3])*360/totalblanknum ;
在上一个扇形的角度基础上加上这个圆心角作为起始角度:degreenew = degree+ degreenew;
由起始角度得到终止hour,min
EHour = degreenew/30;
EMin = degreenew%30*2;
起始hour,min是上一个扇形的终止hour,min
SHour =EHour;
SMin =EMin;
3.由于默认0度 是x轴正方向,即3点钟钟方向,因此在PieHelper中将SHour,EHour,SMin ,EMin 化成角度后 都加上了 270°
4.PieView.java 中拿到 ArrayList<PieHelper> helperList 如何确定 标记数据的坐标
for(int k=0; k< pieArrayList_.size(); k++){ //angle:12点方向起始,顺时针的角度 double angle = pieArrayList_.get(k).getStart()-270+pieArrayList_.get(k).getSweep()/2; //90-angle: 360-(angle-90) 转化成平面坐标系中角度,3点起始,逆时针 float x = (float) (pieCenterPoint.x+Math.cos(Math.toRadians(90-angle))*pieRadius*0.8); float y = (float) (pieCenterPoint.y-Math.sin(Math.toRadians(90-angle))*pieRadius*0.8); canvas.drawText(areanameList.get(k),x, y, textPaint); }
因为要用到正余弦,故将角度转换回 平面直角坐标系中的角度。然后利用公式,根据圆心角坐标以及半径和角度 求出要绘制的数据的坐标
注意这里的
Math.cos(Math.toRadians(90-angle))中的Math.toRadians()函数。
5:我将画数据的步骤和画外围圆圈的步骤放在一起,绘制的时候是数据和圆圈先显示出来,然后扇形绘制,看过demo的都知道pieview和barview绘制都是一个动态的过程。
相当于拿一条带颜色的线扫过圆面,涂上颜色,得到图形。我用了一个和 pieArrayList 数据完全相同的 list pieArrayList_来标记要显示的数据,而用pieArrayList来绘制图形
防止每一次圆面刷新数据都会重新显示因此闪烁的后果,如果大家有别的办法可以在评论里贴出来。
- 【Android开发日记】AndroidCharts 饼状图 PieView修改:添加数值和颜色
- 【Android开发日记】AndroidCharts 柱状图 BarView修改:添加数值和颜色
- 【Android开发日记】 AndroidCharts LineView根据数据自动调整高度
- android开发 修改状态栏背景颜色和字体颜色(工作日记)
- 自定义饼状图控件PieView
- android 中的数值颜色
- AndroidCharts为折线图表添加y坐标
- AndroidCharts为折线图表添加y坐标 .
- 动态修改shape颜色值 android开发
- android开发,修改状态栏字体颜色?
- Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应
- Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应
- Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应
- Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应
- Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应
- Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应
- Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应
- Android开发:setAlpha()方法和常用RGB颜色表----颜色, r g b分量数值(int), 16进制表示 一一对应
- Linux命令之kill
- 【JAVASE】Java同时抛出多个异常
- 平衡二叉树AVL的基本操作之删除
- vector删除元素
- 求二叉树中节点的最大距离
- 【Android开发日记】AndroidCharts 饼状图 PieView修改:添加数值和颜色
- Eclipse快捷键大全(转载)
- Foundation中将字符串写入到磁盘文件上
- Android ActionBar应用实战,高仿微信主界面的设计
- FPGA研发(5)从零开始调试FPGA。
- ioctl相关使用
- HibernateDaoSupport详解
- HDU-2000 ASCII码排序
- OCP 1Z0 053 114