欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

android自定义环形统计图动画

程序员文章站 2022-04-09 17:02:05
本文实例为大家分享了android自定义环形统计图动画的具体代码,供大家参考,具体内容如下一、测试截图二、实现原理package com.freedomanlib; import java.util....

本文实例为大家分享了android自定义环形统计图动画的具体代码,供大家参考,具体内容如下

一、测试截图

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);
 }
 
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

相关标签: android 统计图