android实现饼状图
来源:互联网 发布:windows聚焦图片在哪 编辑:程序博客网 时间:2024/06/06 00:23
package com.vanke.easysale.widget.chart;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PaintFlagsDrawFilter;import android.graphics.Rect;import android.graphics.RectF;import android.support.annotation.Nullable;import android.support.v4.content.ContextCompat;import android.util.AttributeSet;import android.view.View;import com.vanke.IntegratedPlatform.manager.R;import com.vanke.easysale.util.DensityUtil;import java.util.ArrayList;/** * 饼状图 * Created by rantao on 2017/8/26. */public class PieChartView extends View { private int mWidth; // 控件宽度 private int mHeight; // 控件高度 private int mOuterRadius; // 外圆半径 private int mHoleRadius; // 内圆半径 private Paint mPaint; // 画笔 private int[] percentText = {}; // 百分比 private String[] mTexts = {}; // 线条上得文本 private int[] mColors = new int[]{getResources().getColor(R.color.color_e62e3d), getResources().getColor(R.color.color_ffd633), getResources().getColor(R.color.color_e5737c), getResources().getColor(R.color.color_991f29), getResources().getColor(R.color.color_ff0015) }; private int mCenterX; // 圆点X坐标 private int mCenterY; // 圆点Y坐标 private float mStartAngle = -90; // 圆弧开始角度 private ArrayList<PiePoint> mPiePoints = new ArrayList<>(); private int sumTextSize; private String sum = ""; public PieChartView(Context context) { super(context); } public PieChartView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mCenterX = mWidth / 2; mCenterY = mHeight / 2; drawArc(canvas); drawTextForHoleCenter(canvas); drawLine(canvas); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = measure(widthMeasureSpec); int height = measure(heightMeasureSpec); setMeasuredDimension(width, height); updateDimensions(width, height); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); updateDimensions(w, h); } private void updateDimensions(int width, int height) { this.mWidth = width; this.mHeight = height; } private int measure(int measureSpec) { int result = 0; int mode = MeasureSpec.getMode(measureSpec); int size = MeasureSpec.getSize(measureSpec); switch (mode) { case MeasureSpec.EXACTLY: result = size; break; case MeasureSpec.AT_MOST: result = size; break; case MeasureSpec.UNSPECIFIED: break; default: break; } return result; } public void setSum(String sum) { this.sum = sum; } public void setTexts(String[] mTexts) { this.mTexts = mTexts; } public void setPercentText(int[] percentText) { this.percentText = percentText; invalidate(); } /** * 初始化 */ private void init() { mOuterRadius = DensityUtil.dip2px(getContext(), 63); mHoleRadius = DensityUtil.dip2px(getContext(), 38); mPaint = new Paint(); mPaint.setAntiAlias(true); sumTextSize = getResources().getDimensionPixelSize(R.dimen.textsize_18sp); } /** * 画圆弧 * * @param canvas */ private void drawArc(Canvas canvas) { if (null != mPiePoints && mPiePoints.size() > 0) { mPiePoints.clear(); } int startX = mCenterX - mOuterRadius; int endX = mCenterX + mOuterRadius; int startY = mCenterY - mOuterRadius; int endY = mCenterY + mOuterRadius; if (mStartAngle != -90) { mStartAngle = -90; } for (int i = 0; i < percentText.length; i++) { mPaint.setColor(mColors[i]); double ratio = ((double) percentText[i] / 100); float endAngle = (float) (ratio * 360); PiePoint piePoint = new PiePoint(); piePoint.startAngle = mStartAngle; piePoint.endAngle = mStartAngle + endAngle; mPiePoints.add(piePoint); canvas.drawArc(new RectF(startX, startY, endX, endY), mStartAngle, endAngle - 1, true, mPaint); mStartAngle = mStartAngle + endAngle; // 下一个开始角度 // 绘制阴影圆心部分 int left = mCenterX - mHoleRadius; int right = mCenterX + mHoleRadius; int top = mCenterY - mHoleRadius; int bottom = mCenterY + mHoleRadius; Bitmap centerBitmapWithShadow = BitmapFactory.decodeResource(getResources(), R.drawable.ic_piechart_shadow); canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG)); canvas.drawBitmap(centerBitmapWithShadow, null, new RectF(left, top, right, bottom), mPaint); } } /** * 绘制线条 * * @param canvas */ private void drawLine(Canvas canvas) { for (int i = 0; i < mPiePoints.size(); i++) { float centerAngle = (mPiePoints.get(i).startAngle + mPiePoints.get(i).endAngle) / 2; /** * 分四个象限和四个坐标轴进行判断 */ if (centerAngle > 0 && centerAngle < 90) { drawBreakLine(canvas, i, 1); } else if (centerAngle > 90 && centerAngle < 180) { drawBreakLine(canvas, i, 2); } else if (centerAngle > 180 && centerAngle < 270) { drawBreakLine(canvas, i, 3); } else if ((centerAngle > 270 && centerAngle < 360) || (centerAngle > -90 && centerAngle < 0)) { drawBreakLine(canvas, i, 4); } else if (centerAngle == 0) { drawBreakLine(canvas, i, 5); } else if (centerAngle == 90) { drawBreakLine(canvas, i, 6); } else if (centerAngle == 180) { drawBreakLine(canvas, i, 7); } else if (centerAngle == 270) { drawBreakLine(canvas, i, 8); } } } private void drawBreakLine(Canvas canvas, int position, int condition) { float centerAngle = (mPiePoints.get(position).startAngle + mPiePoints.get(position).endAngle) / 2; int xInArc = 0; // 圆弧中心在圆弧上的X坐标 int yInArc = 0; // 圆弧中心在圆弧上的Y坐标 int breakX = 0; // 拐点X坐标 int breakY = 0; // 拐点Y坐标 int lineEndX = 0; // 横线结束X坐标 int lineEndY = 0; // 横线结束Y坐标 float arcNum; mPaint.setColor(mColors[position]); switch (condition) { case 1: arcNum = (float) (Math.PI / 180 * centerAngle); xInArc = (int) (mCenterX + (Math.cos(arcNum) * mOuterRadius)); yInArc = (int) (mCenterY + (Math.sin(arcNum) * mOuterRadius)); breakX = xInArc + DensityUtil.dip2px(getContext(), 5); breakY = yInArc + DensityUtil.dip2px(getContext(), 5); lineEndX = breakX + DensityUtil.dip2px(getContext(), 70); lineEndY = breakY; canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint); canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint); canvas.drawCircle(lineEndX, lineEndY, 5, mPaint); drawTextOnLine(canvas, position, xInArc, breakY, lineEndX); drawTextForEdge(canvas, position, condition, lineEndX + DensityUtil.dip2px(getContext(), 10), lineEndY); break; case 2: arcNum = (float) (Math.PI / 180 * (centerAngle - 90)); xInArc = (int) (mCenterX - Math.sin(arcNum) * mOuterRadius); yInArc = (int) (mCenterY + Math.cos(arcNum) * mOuterRadius); breakX = xInArc - DensityUtil.dip2px(getContext(), 5); breakY = yInArc + DensityUtil.dip2px(getContext(), 5); lineEndX = breakX - DensityUtil.dip2px(getContext(), 70); lineEndY = breakY; canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint); canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint); canvas.drawCircle(lineEndX, lineEndY, 5, mPaint); drawTextOnLine(canvas, position, xInArc, breakY, lineEndX); drawTextForEdge(canvas, position, condition, lineEndX - DensityUtil.dip2px(getContext(), 10), lineEndY); break; case 3: arcNum = (float) (Math.PI / 180 * (centerAngle - 180)); xInArc = (int) (mCenterX - Math.cos(arcNum) * mOuterRadius); yInArc = (int) (mCenterY - Math.sin(arcNum) * mOuterRadius); breakX = xInArc - DensityUtil.dip2px(getContext(), 5); breakY = yInArc - DensityUtil.dip2px(getContext(), 5); lineEndX = breakX - DensityUtil.dip2px(getContext(), 70); lineEndY = breakY; canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint); canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint); canvas.drawCircle(lineEndX, lineEndY, 5, mPaint); drawTextOnLine(canvas, position, xInArc, breakY, lineEndX); drawTextForEdge(canvas, position, condition, lineEndX - DensityUtil.dip2px(getContext(), 10), lineEndY); break; case 4: arcNum = (float) (Math.PI / 180 * (centerAngle - 270)); xInArc = (int) (mCenterX + Math.sin(arcNum) * mOuterRadius); yInArc = (int) (mCenterY - Math.cos(arcNum) * mOuterRadius); breakX = xInArc + DensityUtil.dip2px(getContext(), 5); breakY = yInArc - DensityUtil.dip2px(getContext(), 5); lineEndX = breakX + DensityUtil.dip2px(getContext(), 70); lineEndY = breakY; canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint); canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint); canvas.drawCircle(lineEndX, lineEndY, 5, mPaint); drawTextOnLine(canvas, position, xInArc, breakY, lineEndX); drawTextForEdge(canvas, position, condition, lineEndX + DensityUtil.dip2px(getContext(), 10), lineEndY); break; case 5: // 0度 xInArc = mCenterX + mOuterRadius; yInArc = mCenterY; lineEndX = xInArc + DensityUtil.dip2px(getContext(), 70); lineEndY = yInArc; breakY = yInArc; canvas.drawLine(xInArc, yInArc, lineEndX, lineEndY, mPaint); canvas.drawCircle(lineEndX, lineEndY, 5, mPaint); drawTextOnLine(canvas, position, xInArc, breakY, lineEndX); drawTextForEdge(canvas, position, condition, lineEndX, lineEndY); break; case 6: // 90度 xInArc = mCenterX; yInArc = mCenterY + mOuterRadius; breakX = xInArc; breakY = yInArc + DensityUtil.dip2px(getContext(), 10); lineEndX = xInArc + DensityUtil.dip2px(getContext(), 70); lineEndY = breakY; canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint); canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint); canvas.drawCircle(lineEndX, lineEndY, 5, mPaint); drawTextOnLine(canvas, position, xInArc, breakY, lineEndX); drawTextForEdge(canvas, position, condition, lineEndX, lineEndY); break; case 7: // 180度 xInArc = mCenterX - mOuterRadius; yInArc = mCenterY; lineEndX = xInArc - DensityUtil.dip2px(getContext(), 70); lineEndY = yInArc; breakY = yInArc; canvas.drawLine(xInArc, yInArc, lineEndX, lineEndY, mPaint); canvas.drawCircle(lineEndX, lineEndY, 5, mPaint); drawTextOnLine(canvas, position, xInArc, breakY, lineEndX); drawTextForEdge(canvas, position, condition, lineEndX, lineEndY); break; case 8: // 270度 xInArc = mCenterX; yInArc = mCenterY - mOuterRadius; breakX = xInArc; breakY = yInArc - DensityUtil.dip2px(getContext(), 10); lineEndX = breakX + DensityUtil.dip2px(getContext(), 70); lineEndY = breakY; canvas.drawLine(xInArc, yInArc, breakX, breakY, mPaint); canvas.drawLine(breakX, breakY, lineEndX, lineEndY, mPaint); canvas.drawCircle(lineEndX, lineEndY, 5, mPaint); drawTextOnLine(canvas, position, xInArc, breakY, lineEndX); drawTextForEdge(canvas, position, condition, lineEndX, lineEndY); break; default: break; } } private void drawTextForHoleCenter(Canvas canvas) { if (percentText.length != 0) { /** * 绘制总数动态文本 */ int left = mCenterX - DensityUtil.dip2px(getContext(), 10); int right = mCenterX + DensityUtil.dip2px(getContext(), 10); int top = mCenterY + DensityUtil.dip2px(getContext(), 5); int bottom = mCenterY + DensityUtil.dip2px(getContext(), 15); Rect rect = new Rect(left, top, right, bottom); Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); int baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2; mPaint.setTextAlign(Paint.Align.CENTER); sumTextSize = getResources().getDimensionPixelSize(R.dimen.textsize_18sp); mPaint.setTextSize(sumTextSize); mPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_333333)); canvas.drawText(sum, rect.centerX(), baseline, mPaint); /** * 绘制"总数"静态文本 */ left = mCenterX - DensityUtil.dip2px(getContext(), 7); right = mCenterX + DensityUtil.dip2px(getContext(), 7); top = mCenterY - DensityUtil.dip2px(getContext(), 13); bottom = mCenterY - DensityUtil.dip2px(getContext(), 3); rect = new Rect(left, top, right, bottom); baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2; mPaint.setTextAlign(Paint.Align.CENTER); sumTextSize = getResources().getDimensionPixelSize(R.dimen.textsize_12sp); mPaint.setTextSize(sumTextSize); mPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_999999)); canvas.drawText("总数", rect.centerX(), baseline, mPaint); } } /** * 绘制线条上的文本 * * @param canvas */ private void drawTextOnLine(Canvas canvas, int position, int startX, int startY, int endX) { int startYTmp = startY - DensityUtil.dip2px(getContext(), 10); int endYTmp = startY - DensityUtil.dip2px(getContext(), 5); Rect rect = new Rect(startX, startYTmp, endX, endYTmp); Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); int baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2; mPaint.setTextAlign(Paint.Align.CENTER); sumTextSize = getResources().getDimensionPixelSize(R.dimen.textsize_10sp); mPaint.setTextSize(sumTextSize); mPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_999999)); canvas.drawText(mTexts[position], rect.centerX(), baseline, mPaint); } /** * 绘制线条边缘文本 * * @param canvas */ private void drawTextForEdge(Canvas canvas, int position, int codition, int edgeX, int centerY) { Rect rect = null; switch (codition) { case 1: rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5), edgeX + DensityUtil.dip2px(getContext(), 10), centerY + DensityUtil.dip2px(getContext(), 5)); break; case 2: rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5), edgeX - DensityUtil.dip2px(getContext(), 10), centerY + DensityUtil.dip2px(getContext(), 5)); break; case 3: rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5), edgeX - DensityUtil.dip2px(getContext(), 10), centerY + DensityUtil.dip2px(getContext(), 5)); break; case 4: rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5), edgeX + DensityUtil.dip2px(getContext(), 10), centerY + DensityUtil.dip2px(getContext(), 5)); break; case 5: // 0度 rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5), edgeX + DensityUtil.dip2px(getContext(), 30), centerY + DensityUtil.dip2px(getContext(), 5)); break; case 6: // 90度 rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5), edgeX + DensityUtil.dip2px(getContext(), 30), centerY + DensityUtil.dip2px(getContext(), 5)); break; case 7: // 180度 rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5), edgeX - DensityUtil.dip2px(getContext(), 30), centerY + DensityUtil.dip2px(getContext(), 5)); break; case 8: // 270度 rect = new Rect(edgeX, centerY - DensityUtil.dip2px(getContext(), 5), edgeX + DensityUtil.dip2px(getContext(), 30), centerY + DensityUtil.dip2px(getContext(), 5)); break; default: break; } Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); int baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2; mPaint.setTextAlign(Paint.Align.CENTER); sumTextSize = getResources().getDimensionPixelSize(R.dimen.textsize_12sp); mPaint.setTextSize(sumTextSize); mPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_333333)); String percent = percentText[position] + "%"; canvas.drawText(percent, rect.centerX(), baseline, mPaint); } class PiePoint { float startAngle; float endAngle; }}
阅读全文
0 0
- android实现饼状图
- 【Android】android实现画板
- Android开发自定义控件实现一个饼状图
- android柱状图和饼状图的的实现
- 【Android】Android自动开关机实现
- 【Android】Android聊天机器人实现
- 【android】:android实现读取通讯录
- 使用 Android 实现联网
- Android LsitView的实现
- android实现拖动效果
- Android 倒影实现算法
- android 实现拖动效果
- 使用 Android 实现联网
- android 实现gif播放
- Android实现拖动效果
- android 监听的实现
- Android截图代码实现
- android实现tabs分页
- jedis高级使用
- WPF转换器添加
- vue之mock.js模拟接口
- 输入流的数字求和(空格隔开)
- JavaScript(九)DOM
- android实现饼状图
- Caffe源码理解(2)——超级完整版教程:如何自定义一个新的层结构并重新编译Caffe
- Error C2061:语法错误
- Activity反复进入退出OOM
- 从redis获取图片展示到jsp
- 设计模式之单例模式
- 生成多个不重复的随机数字php
- JS对象:offset、scroll、event、client
- OpenGL坐标变换矩阵