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

}

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

(0)

相关推荐

  • Android编程实现canvas绘制柱状统计图功能【自动计算宽高及分度值、可左右滑动】

    本文实例讲述了Android编程实现canvas绘制柱状统计图功能.分享给大家供大家参考,具体如下: 这里实现了一个简单的柱状统计图,如下:   特点: 1.根据数据源自动计算每个条目的高度.宽度.间距,自动计算分度值. 2.当条目数较多时,可左右滑动查看全部内容,图形.文字同步滑动,并且松手后会渐渐的停下来(而不是立刻停下来). 代码: (1)核心代码:BarChartView.Java package com.sina.appbarchart; import android.app.Acti

  • Android自定义View实现多边形统计图示例代码

    前言   最近利用空闲时间学习了自定义View的一些知识,为了巩固,写了一个小东西,顺便分享出来,下面话不多说了,来一起看看详细的介绍吧. 简介   一个多边形统计图.边数,每个方向的值,每个点的文字等等都是可以设置的. 下面就来分析一下这个自定义View 这个view由以下几个部分组成 M层N边形 中心到各顶点的连线 填充区域 文字 @Override protected void onDraw(Canvas canvas) { if (!canDraw()) { return; } canv

  • Android自定义条形对比统计图

    本文实例为大家分享了Android自定义条形对比统计图的具体代码,供大家参考,具体内容如下 一.测试截图 二.实现方法 package com.xtravel.widget; import java.util.Timer; import java.util.TimerTask; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import

  • Android 实现会旋转的饼状统计图实例代码

    Android 实现会旋转的饼状统计图实例代码 最近在做一个项目,由于有需要统计的需要,于是就做成了下面饼状统计图. 下图是效果图: 大致思路是: 关于的介绍这里不做详细介绍,如果想深入请点击开源项目MPAndroidChart 下面是其实现: 首先是添加MPAndroidChart依赖: maven { url "https://jitpack.io" } compile 'com.github.PhilJay:MPAndroidChart:v3.0.1' Mainactivity

  • Android编程实现canvas绘制饼状统计图功能示例【自动适应条目数量与大小】

    本文实例讲述了Android编程实现canvas绘制饼状统计图功能.分享给大家供大家参考,具体如下: 本例的目的是实现一个简单的饼状统计图,效果如下:    特点: 1.使用非常方便,可放在xml布局文件中,然后在代码中设置内容,即: PieChartView pieChartView = (PieChartView) findViewById(R.id.pie_chart); PieChartView.PieItemBean[] items = new PieChartView.PieItem

  • Android自定义View——扇形统计图的实现代码

    Android 扇形统计图 先看看效果: 看上去如果觉得还行就继续往下看吧! 自定义View 定义成员变量 private int mHeight, mWidth;//宽高 private Paint mPaint;//扇形的画笔 private Paint mTextPaint;//画文字的画笔 private int centerX, centerY;//中心坐标 //"其他"的value //扇形图分成太多快 所以要合并一部分为其他 即图中灰色部分 private double

  • 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自定义环形对比图效果

    本文实例为大家分享了android自定义环形对比图的具体代码,供大家参考,具体内容如下 1.首先在res/values里创建一个attr.xml的文件. <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="AnswerChartView"> <attr name="radius" for

  • Android自定义水波纹动画Layout实例代码

    话不多说,我们先来看看效果: Hi前辈搜索预览 这一张是<Hi前辈>的搜索预览图,你可以在这里下载这个APP查看更多效果: http://www.wandoujia.com/apps/com.superlity.hiqianbei LSearchView 这是一个MD风格的搜索框,集成了ripple动画以及search时的loading,使用很简单,如果你也需要这样的搜索控件不妨来试试:https://github.com/onlynight/LSearchView RippleEverywh

  • Android自定义带增长动画和点击弹窗提示效果的柱状图DEMO

    项目中最近用到各种图表,本来打算用第三方的,例如MPAndroid,这是一个十分强大的图表库,应用起来十分方便,但是最终发现和设计不太一样,没办法,只能自己写了.今天将写好的柱状图的demo贴在这,该柱状图可根据数据的功能有一下几点: 1. 根据数据的多少,动态的绘制柱状图柱子的条数: 2. 柱状图每条柱子的绘制都有动态的动画效果: 3. 每条柱子有点击事件,点击时弹出提示框,显示相关信息,规定时间后,弹窗自动消失. 好了,先上演示图: 下边贴出相关代码: 自定义柱状图类: package co

  • Android 自定义加载动画Dialog弹窗效果的示例代码

    效果图 首先是创建弹窗的背景 这是上面用到的 以shape_bg_5_blue.xml为例,其他的三个无非就是里面的颜色不一样而已 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <corners android:radius="5dp"

  • Android自定义PopWindow带动画向下弹出效果

    本文实例为大家分享了PopWindow实现带动画向下弹出效果的具体代码,供大家参考,具体内容如下 首先建一个popwin的实体类 package dmpte.mytest; import android.content.Context; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.PopupWindow; i

  • Android自定义环形LoadingView效果

    最近项目有要用到环形的进度条,Github上有一个类似的DashedCircularProgress控件,但是他画的进度是通过设置画笔的虚线效果来实现间隔的:progressPaint.setPathEffect(new DashPathEffect(new float[]{dashWith, dashSpace}, dashSpace));如果内层还有一层圆环,在动态设置时,内层和外层有细微的偏差.于是我在原有基础上改了一个,实现了我要的效果(设置进度时可以选择加动画或者不加动画): 控件实现

  • Android自定义view之围棋动画效果的实现

    前言 废话不多说直接开始 老规矩,文章最后有源码 完成效果图 棋子加渐变色 棋子不加渐变色 一.测量 1.获取宽高 @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = w; mHeight = h; useWidth = mWidth; if (mWidth > mHeight) { useWidth =

  • Android SeekBar 自定义thumb旋转动画效果

    目录 简介 示例 dimens.xml drawable shape_thumb_round_1.xml layers_thumb_ring_sweep_1.xml rotate_thumb_1.xml layers_seek_bar_progress_1.xml layout Activity中调用 小结 简介 某些音乐播放或者视频播放的界面上,资源还在加载时,进度条的原点(thumb)会显示一个转圈的效果. 资源加载完成后,又切换回静态效果.这个效果增强了用户体验. 一般来说有美术人员负责设

随机推荐