android自定义环形统计图动画
程序员文章站
2022-04-09 17:02:05
本文实例为大家分享了android自定义环形统计图动画的具体代码,供大家参考,具体内容如下一、测试截图二、实现原理package com.freedomanlib; import java.util....
本文实例为大家分享了android自定义环形统计图动画的具体代码,供大家参考,具体内容如下
一、测试截图
二、实现原理
package com.freedomanlib; import java.util.timer; import java.util.timertask; import android.annotation.suppresslint; import android.content.context; import android.graphics.canvas; import android.graphics.color; import android.graphics.paint; import android.graphics.rectf; import android.graphics.typeface; import android.util.attributeset; import android.util.log; import android.view.motionevent; import android.view.view; /** * @name 自定义车辆数据统计比重环 * 1、比重环由底环(灰色)、里程环(红色)、平均速度环(黄色)、行驶时间环(蓝色)、超速次数环(绿色)、环中间评级、指示器组成 * ,其中四个数据统计环和底环是同心圆、圆心处有评分文本,圆环外是四个统计指示器。<br> * 2、四个统计环是四个弧线,弧度由外界提供数据,并动态显示在界面上。<br> * 3、评分等级分为三种:未评分、正在评分、评分完成,当用户点击中间区域时开启评分,评分结束自动停止。<br> * 4、外侧对应的四个指示器上结构上包括:指示器位置的小圆圈、折线连接线、指示文本、文本数据显示具体的数值。<br> * * @author freedoman * @date 2014-10-27 */ public class cirstatisticgraph extends view { private static final string tag = "cirstatisticgraph"; /** * @name centerpoint * @descripation 中心点<br> */ class centerpoint { float x; float y; } /** * 边界宽高、中心坐标、外环和内环半径 */ private float boundswidth; private float boundsheigh; private centerpoint centerpoint = new centerpoint(); private float radius; private float paintwidth; private float genpaintwidth; /** * 几种不同的画笔 */ private paint defaultpaint; private paint genpaint; private paint progresstextpaint; private paint flagpaint; /** * 进度 */ private int curprogress; private int targetprogress = 88; private boolean complete; private int mileage = 128; private int averagespeed = 78; private float gotime = 1.5f; private int overspeedcount = 3; /** * 构造 * * @param context */ public cirstatisticgraph(context context) { this(context, null); } public cirstatisticgraph(context context, attributeset attrs) { super(context, attrs, 0); } public cirstatisticgraph(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); this.initialize(); } /** * 初始化 */ private void initialize() { // 底环画笔 defaultpaint = new paint(); defaultpaint.setcolor(color.argb(0xee, 0x8e, 0x8e, 0x8e)); defaultpaint.setstyle(paint.style.stroke); defaultpaint.setstrokewidth(paintwidth); defaultpaint.setantialias(true); // 比重环画笔 genpaint = new paint(); genpaint.setstyle(paint.style.stroke); genpaint.setstrokewidth(genpaintwidth); genpaint.setantialias(true); // 中心进度文本和评级画笔 progresstextpaint = new paint(); progresstextpaint.setcolor(color.white); progresstextpaint.setstyle(paint.style.stroke); progresstextpaint.setstrokewidth(0); progresstextpaint.settypeface(typeface.default_bold); // 指示器画笔 flagpaint = new paint(); flagpaint.setcolor(color.white); flagpaint.setstyle(paint.style.stroke); flagpaint.setstrokewidth(3); flagpaint.setantialias(true); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); // 绘制区域的宽高 boundswidth = getwidth(); boundsheigh = getheight(); centerpoint.x = boundswidth / 2; centerpoint.y = boundsheigh / 2; radius = boundsheigh * 1 / 3; paintwidth = 50; genpaintwidth = paintwidth / 7; initialize(); } /** * 启动进度动画 */ public void start() { curprogress = 0; if (targetprogress == 0) { targetprogress = 88; } final timer timer = new timer(); timertask timertask = new timertask() { @override public void run() { curprogress++; if (curprogress == targetprogress) { timer.cancel(); } postinvalidate(); } }; timer.schedule(timertask, 0, 20); } @suppresslint("drawallocation") @override public void ondraw(canvas canvas) { super.ondraw(canvas); // 底环(灰色) canvas.drawcircle(centerpoint.x, centerpoint.y, radius, defaultpaint); // 很重要的一个半径(最外层环即里程环的半径) float sroundradius = radius + paintwidth / 2 - genpaintwidth / 2; // 里程比重环(红色) genpaint.setcolor(color.argb(0xee, 0xff, 0x35, 0x9a)); rectf oval1 = new rectf(centerpoint.x - sroundradius, centerpoint.y - sroundradius, centerpoint.x + sroundradius, centerpoint.y + sroundradius); canvas.drawarc(oval1, -90, 300, false, genpaint); // 里程比重环的指示器位置(勾股定理计算坐标) float temp = sroundradius; float relativepoint = (float) math.sqrt(temp * temp / 2); canvas.drawcircle(centerpoint.x - relativepoint, centerpoint.y - relativepoint, radius / 12, flagpaint); // 连线 float[] pts1 = new float[8]; pts1[0] = centerpoint.x - relativepoint - radius / 24; pts1[1] = centerpoint.y - relativepoint - radius / 24; pts1[2] = centerpoint.x - relativepoint - 80; pts1[3] = centerpoint.y - relativepoint - 40; pts1[4] = pts1[2]; pts1[5] = pts1[3]; pts1[6] = pts1[4] - 50; pts1[7] = pts1[5]; canvas.drawlines(pts1, flagpaint); // 文本 progresstextpaint.settextsize(30); string txt = "里程"; float wt = progresstextpaint.measuretext(txt); canvas.drawtext(txt, pts1[6] - wt - 10, pts1[7] + 15, progresstextpaint); if (complete) { canvas.drawtext(mileage + "km", pts1[6] - wt - 10, pts1[7] + 50, progresstextpaint); } // 平均速度环(黄色) genpaint.setcolor(color.argb(0xee, 0xf7, 0x50, 0x00)); rectf oval2 = new rectf(centerpoint.x - sroundradius + 2 * genpaintwidth, centerpoint.y - sroundradius + 2 * genpaintwidth, centerpoint.x + sroundradius - 2 * genpaintwidth, centerpoint.y + sroundradius - 2 * genpaintwidth); canvas.drawarc(oval2, 0, 280, false, genpaint); // 平均速度环的指示器位置 temp = sroundradius - 2 * genpaintwidth; relativepoint = (float) math.sqrt(temp * temp / 2); canvas.drawcircle(centerpoint.x + relativepoint, centerpoint.y - relativepoint, radius / 12, flagpaint); // 连接线 pts1 = new float[8]; pts1[0] = centerpoint.x + relativepoint + radius / 24; pts1[1] = centerpoint.y - relativepoint - radius / 24; pts1[2] = centerpoint.x + relativepoint + 80; pts1[3] = centerpoint.y - relativepoint - 40; pts1[4] = pts1[2]; pts1[5] = pts1[3]; pts1[6] = pts1[4] + 50; pts1[7] = pts1[5]; canvas.drawlines(pts1, flagpaint); // 文本 txt = "平均速度"; wt = progresstextpaint.measuretext(txt); canvas.drawtext(txt, pts1[6] + 10, pts1[7] + 15, progresstextpaint); if (complete) { canvas.drawtext(averagespeed + "km/h", pts1[6] + 10, pts1[7] + 50, progresstextpaint); } // 行驶时间环(蓝色)和指示 genpaint.setcolor(color.argb(0xee, 0x00, 0x72, 0xe3)); rectf oval3 = new rectf(centerpoint.x - sroundradius + 4 * genpaintwidth, centerpoint.y - sroundradius + 4 * genpaintwidth, centerpoint.x + sroundradius - 4 * genpaintwidth, centerpoint.y + sroundradius - 4 * genpaintwidth); canvas.drawarc(oval3, 90, 270, false, genpaint); // 行驶时间环指示器的位置 temp = sroundradius - 4 * genpaintwidth; relativepoint = (float) math.sqrt(temp * temp / 2); canvas.drawcircle(centerpoint.x - relativepoint, centerpoint.y + relativepoint, radius / 12, flagpaint); // 连接线和文本 pts1 = new float[8]; pts1[0] = centerpoint.x - relativepoint - radius / 24; pts1[1] = centerpoint.y + relativepoint + radius / 24; pts1[2] = centerpoint.x - relativepoint - 80; pts1[3] = centerpoint.y + relativepoint + 40; pts1[4] = pts1[2]; pts1[5] = pts1[3]; pts1[6] = pts1[4] - 50; pts1[7] = pts1[5]; canvas.drawlines(pts1, flagpaint); txt = "行驶时间"; wt = progresstextpaint.measuretext(txt); canvas.drawtext(txt, pts1[6] - wt - 10, pts1[7] + 15, progresstextpaint); if (complete) { canvas.drawtext(gotime + "h", pts1[6] - wt - 10, pts1[7] - 20, progresstextpaint); } // 超速次数环(绿色) genpaint.setcolor(color.argb(0xee, 0x00, 0xec, 0x00)); rectf oval4 = new rectf(centerpoint.x - sroundradius + 6 * genpaintwidth, centerpoint.y - sroundradius + 6 * genpaintwidth, centerpoint.x + sroundradius - 6 * genpaintwidth, centerpoint.y + sroundradius - 6 * genpaintwidth); canvas.drawarc(oval4, 0, 290, false, genpaint); // 超速次数环指示器的位置 temp = sroundradius - 6 * genpaintwidth; relativepoint = (float) math.sqrt(temp * temp / 2); canvas.drawcircle(centerpoint.x + relativepoint, centerpoint.y + relativepoint, radius / 12, flagpaint); // 连接线 pts1 = new float[8]; pts1[0] = centerpoint.x + relativepoint + radius / 24; pts1[1] = centerpoint.y + relativepoint + radius / 24; pts1[2] = centerpoint.x + relativepoint + 80; pts1[3] = centerpoint.y + relativepoint + 40; pts1[4] = pts1[2]; pts1[5] = pts1[3]; pts1[6] = pts1[4] + 50; pts1[7] = pts1[5]; canvas.drawlines(pts1, flagpaint); // 文本 txt = "超速次数"; wt = progresstextpaint.measuretext(txt); canvas.drawtext(txt, pts1[6] + 10, pts1[7] + 15, progresstextpaint); if (complete) { canvas.drawtext(overspeedcount + "次", pts1[6] + 10, pts1[7] - 20, progresstextpaint); } // 环中心进度文本(动态迭加的) int curpercent = curprogress; progresstextpaint.settextsize(60); float ww = progresstextpaint.measuretext(curpercent + "%"); canvas.drawtext(curpercent + "%", centerpoint.x - ww / 2, centerpoint.y, progresstextpaint); // 评级提示 progresstextpaint.settextsize(25); float w = 0; string text = ""; if (curpercent == 0) { // 暂未评级 text = "暂未评级"; w = progresstextpaint.measuretext(text); complete = false; } else if (curpercent < targetprogress) { // 评级中... text = "评级中..."; w = progresstextpaint.measuretext(text); } else if (curpercent == targetprogress) { // 评级完成 text = "评级完成"; w = progresstextpaint.measuretext(text); complete = true; postinvalidate(); } canvas.drawtext(text, centerpoint.x - w / 2, centerpoint.y + 40, progresstextpaint); } /** * 点击评分区域,进行评分 * * @param event * @return */ @override public boolean ontouchevent(motionevent event) { float x = event.getx(); float y = event.gety(); if (x > centerpoint.x - radius && x < centerpoint.x + radius && y > centerpoint.y - radius && y < centerpoint.y + radius) { log.i(tag, ">>>"); start(); } return super.ontouchevent(event); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Flutter 使用Navigator进行局部跳转页面的方法
下一篇: 微信小程序实现吸顶特效