一、测试截图

二、实现方法

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.graphics.Color;
import android.graphics.Paint;
import android.view.View;/*** @name 自定义数据中心旅客分析变化趋势图* @Descripation <br>*               1、根据用户提供的数据(两组float[]数)智能绘制数据的对比条形图。<br>*               2、绘制图表信息:边框、表名、建立二维坐标系、刻度数量、刻度值、单位、网络线、图例、数据系列。<br>*               3、其中Y轴的最大刻度值是用户所提供数据中float[]的最大值,分度值是最大刻度值与刻度数目的比。<br>*               4、绘制用户数据对比条形图:启动线程,遍历数组值,不断在原图上刷新。<br>* @author Freedoman* @date 2014-9-17* @version 1.0*/
public class DataCenterCustomBarChart extends View {// 框架起点坐标、中心坐标、宽高private final int FRAME_X = 20;private final int FRAME_Y = 20;private final int FRAME_WIDTH = 1000;private final int FRAME_HEIGHT = 350;private final int FRAME_CENTER_X = FRAME_WIDTH / 2 + FRAME_X;private final int FRAME_CENTER_Y = FRAME_HEIGHT / 2 + FRAME_Y;// 二维坐标系原点坐标private final int ORIGIN_X = FRAME_X + 100;private final int ORIGIN_Y = FRAME_Y + FRAME_HEIGHT - 100;// XY轴终点坐标private final int XAXIS_X = FRAME_X + FRAME_WIDTH - 200;private final int XAXIS_Y = ORIGIN_Y;private final int YAXIS_X = ORIGIN_X;private final int YAXIS_Y = FRAME_Y + 50;// XY轴刻度数private int countX;private int countY;// XY轴分度值、真实数据分度值private float intervalX;private float intervalY;private float intervalPress;// 单位名称private String nameX;private String nameY;// 图表名称private String chartTitle;// 用户数据private int[] data1;private int[] data2;private int currentPosition;/*** 用户建立图表* * @param context* @param chartTitle*            表名称* @param nameXAxis*            X轴单位* @param nameYAxis*            Y轴单位* @param countY*            Y轴刻度数目* @param thisYearWeekPerson*            用户数据* @param lastYearWeekPerson*            用户数据*/public DataCenterCustomBarChart(Context context, String chartTitle,String nameXAxis, String nameYAxis, int countY,int[] thisYearWeekPerson, int[] lastYearWeekPerson) {super(context);this.chartTitle = chartTitle;// x轴刻度数量以用户数据最大数据为依据,y轴刻度数量由用户来指定this.countX = thisYearWeekPerson.length > lastYearWeekPerson.length ? thisYearWeekPerson.length: lastYearWeekPerson.length;this.countY = countY;this.nameX = nameXAxis;this.nameY = nameYAxis;this.data1 = thisYearWeekPerson;this.data2 = lastYearWeekPerson;// 计算XY轴分度值 = 轴长/刻度数this.intervalX = (XAXIS_X - ORIGIN_X) / countX;this.intervalY = (ORIGIN_Y - YAXIS_Y) / countY;// 计算用户数据分度值 = 用户数据最大值/ 刻度数float max1 = findMaxData(thisYearWeekPerson);float max2 = findMaxData(lastYearWeekPerson);this.intervalPress = (max1 > max2 ? max1 : max2) / countY;// startDrawDynomicBar();}/*** 动态绘制任务*/public void freshDynomicBar() {final Timer timer = new Timer();TimerTask timerTask = new TimerTask() {@Overridepublic void run() {currentPosition++;postInvalidate();if (currentPosition == countX) {timer.cancel();}}};timer.schedule(timerTask, 100, 800);}/*** 绘制图表*/@SuppressLint("DrawAllocation")public void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.WHITE);Paint paint = new Paint();initAXIS(canvas, paint, chartTitle);drawDynamicBar1(canvas, paint, data1);drawDynamicBar2(canvas, paint, data2);}/*** 初始化图表基本信息<br>* 表名、坐标系、刻度数量、刻度值、网络线、图例、数据系列* * @param canvas*/private void initAXIS(Canvas canvas, Paint paint, String chartTitle) {// 画边框paint.setColor(Color.GRAY);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(6);canvas.drawRect(FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT, paint);// 画坐标轴paint.setColor(Color.BLACK);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(5);// X轴及方向箭头canvas.drawLine(ORIGIN_X, ORIGIN_Y, XAXIS_X, XAXIS_Y, paint);canvas.drawLine(XAXIS_X, XAXIS_Y, XAXIS_X - 10, XAXIS_Y - 10, paint);canvas.drawLine(XAXIS_X, XAXIS_Y, XAXIS_X - 10, XAXIS_Y + 10, paint);// Y轴及方向箭头canvas.drawLine(ORIGIN_X, ORIGIN_Y, YAXIS_X, YAXIS_Y, paint);canvas.drawLine(YAXIS_X, YAXIS_Y, YAXIS_X - 10, YAXIS_Y + 10, paint);canvas.drawLine(YAXIS_X, YAXIS_Y, YAXIS_X + 10, YAXIS_Y + 10, paint);// 图表名称(2014年五月第一周)paint.setColor(Color.BLACK);paint.setStyle(Paint.Style.FILL);paint.setTextSize(20);// 设置字体大小paint.setStrokeWidth(2);canvas.drawText(chartTitle, FRAME_CENTER_X - 100, FRAME_Y + 30, paint);// 绘制数据系列20*20矩形(今年、去年)paint.setColor(Color.CYAN);canvas.drawRect(FRAME_WIDTH - 100, FRAME_CENTER_Y - 30,FRAME_WIDTH - 70, FRAME_CENTER_Y, paint);canvas.drawText("今年", FRAME_WIDTH - 60, FRAME_CENTER_Y, paint);paint.setColor(Color.MAGENTA);canvas.drawRect(FRAME_WIDTH - 100, FRAME_CENTER_Y, FRAME_WIDTH - 70,FRAME_CENTER_Y + 30, paint);canvas.drawText("去年", FRAME_WIDTH - 60, FRAME_CENTER_Y + 30, paint);// 画网格线paint.setColor(Color.GRAY);paint.setStyle(Paint.Style.STROKE);paint.setStrokeWidth(2);// 横线(从x轴依次向上画)for (int i = 0; i <= countY; i++) {canvas.drawLine(ORIGIN_X, ORIGIN_Y - i * intervalY, XAXIS_X,ORIGIN_Y - i * intervalY, paint);}// 竖线(从y轴依次向右画)for (int i = 0; i <= countX; i++) {canvas.drawLine(ORIGIN_X + i * intervalX, ORIGIN_Y, ORIGIN_X + i* intervalX, YAXIS_Y, paint);}// X轴刻度值(沿X轴方向1、2、3...),轴名称paint.setColor(Color.BLUE);paint.setStyle(Paint.Style.FILL);paint.setStrokeWidth(2);paint.setTextSize(30);for (int i = 0; i <= countX; i++) {canvas.drawText("" + i, ORIGIN_X + i * intervalX, ORIGIN_Y + 50,paint);}paint.setTextSize(20);// Y轴刻度值(沿Y轴方向,用户提供的数据)轴名称for (int i = 1; i <= countY; i++) {canvas.drawText("" + (int) (i * intervalPress), ORIGIN_X - 80,ORIGIN_Y - i * intervalY + 5, paint);}paint.setTextSize(20);canvas.drawText("(" + nameX + ")", XAXIS_X + 40, XAXIS_Y + 50, paint);canvas.drawText("(" + nameY + ")", YAXIS_X - 30, YAXIS_Y - 20, paint);}/*** 绘制data1变化趋势线 <br>*/@SuppressLint("ResourceAsColor")private void drawDynamicBar1(Canvas canvas, Paint paint, int[] data) {float curRectX_data1 = ORIGIN_X + intervalX - 30;float curRectY_data1;for (int i = 1; i < currentPosition; i++, curRectX_data1 += intervalX) {// 绘制data1的动态条形paint.setColor(Color.CYAN);curRectY_data1 = data[i - 1] / intervalPress * intervalY;canvas.drawRect(curRectX_data1, ORIGIN_Y - curRectY_data1,curRectX_data1 + 30, ORIGIN_Y, paint);}}/*** 绘制data2变化趋势线*/@SuppressLint("ResourceAsColor")private void drawDynamicBar2(Canvas canvas, Paint paint, int[] data) {float curRectX_data2 = ORIGIN_X + intervalX;float curRectY_data2;for (int i = 1; i < currentPosition; i++, curRectX_data2 += intervalX) {// 绘制data2的动态条形paint.setColor(Color.MAGENTA);curRectY_data2 = data[i - 1] / intervalPress * intervalY;canvas.drawRect(curRectX_data2, ORIGIN_Y - curRectY_data2,curRectX_data2 + 30, ORIGIN_Y, paint);}}/*** 查找数组的最大值* * @param data* @return float*/private int findMaxData(int[] data) {int max = data[0];for (int i = 1; i < data.length; i++) {if (data[i] > max) {max = data[i];}}return max;}/*** 计算今年游客数相对去年的增长率* * @return float 增长率百分数*/public float getGrowthRate() {float sumYear = 0, sumLastYear = 0;for (int i = 0; i < data1.length; i++) {sumYear += data1[i];sumLastYear += data2[i];}return (sumYear - sumLastYear) / sumLastYear * 100;}/*** 统计一周总人数* * @return int 人数*/public int getSumWeek() {int sum = 0;for (int i = 0; i < data1.length; i++) {sum += data1[i];}return sum;}/*** 统计一周平均每天旅客数量* * @return int*/public int getAverageWeek() {return getSumWeek() / data1.length;}
}

三、总结

自定义条形对比统计图相关推荐

  1. R语言使用ggpubr包的ggbarplot函数可视化水平偏差条形图(计算数值的z-score、自定义填充色、自定义条形边缘色、自定义调色板、条形图全局排序从小到大、文本标签角度、添加图例标签、轴标签

    R语言使用ggpubr包的ggbarplot函数可视化水平偏差条形图(计算数值的z-score.自定义填充色.自定义条形边缘色.自定义调色板.条形图全局排序从小到大.文本标签角度.添加图例标签.轴标签 ...

  2. R语言ggplot2可视化柱状图并自定义柱体的宽度(通过变量指定条形的宽度)实战、条形图并自定义条形的宽度实战

    R语言ggplot2可视化柱状图并自定义柱体的宽度(通过变量指定条形的宽度)实战.条形图并自定义条形的宽度实战 目录

  3. Python-Matplotlib可视化(6)——自定义坐标轴让统计图清晰易懂

    Python-Matplotlib可视化(6)--自定义坐标轴让统计图清晰易懂 前言 控制刻度间距 控制刻度标签 更简单的设置方式 高级刻度标签控制 使用对数刻度 使用极坐标 系列链接 前言 在系列博 ...

  4. android自动画线,Android自定义View——扇形统计图

    Android 扇形统计图 先看看效果: 看上去如果觉得还行就继续往下看吧! 效果图1 效果图2 自定义View 定义成员变量 private int mHeight, mWidth;//宽高 pri ...

  5. C#自定义规则对比两个集合的对象是否相等

    IList<获取的类> ret = 类的结果集;return ret.Except(另一个相同类型的对象列表集, new AClassComPare()):public class ACl ...

  6. ios自定义条形进度条

    2019独角兽企业重金招聘Python工程师标准>>> 题记 在今天这个变化多端的世界,我们最大的危险不是外界的压力与竞争,而是我们内心的模式,这些模式决定我们看到些什么,感受到些什 ...

  7. 【Flutter 专题】114 图解自定义 ACEProgressPainter 对比进度图

    _paint-color = rightColor ?? _kProRightColor); 2. 异常比例 对于比例过小或过大的情况,小菜计划展示一个固定的三角形,并且在此状况下不进行文字绘制: / ...

  8. 利用while True: break 解决 asyncio:Future exception was never retrieved !

    在if 循环中,break的作用 def test1():my_redis = Redis(db=7)for i in range(1, 1000):my_redis.lpush("redi ...

  9. Python-Matplotlib可视化(7)——多方面自定义统计图绘制

    Python-Matplotlib可视化(7)--多方面自定义统计图绘制 前言 多个子图的合成 为每个子图添加标题 子图合成的另一种方法 更简洁的方法 等比例缩放坐标轴 设置坐标轴范围 设置图形比例 ...

最新文章

  1. android自定义滑块解锁,android 滑动解锁
  2. 二叉树的基本特性和二叉树的几种基本操作的机制_笃学不倦|二叉树(一)
  3. 初等数论--同余方程--同余方程组:中国剩余定理
  4. 微信小程序----手势锁详解
  5. LIMIT M,N分页性能优化方案
  6. 人口增量超过北上广!二线城市是怎样逆袭的?
  7. github在线执行_什么是Github操作,如何自动执行测试和Slack通知?
  8. Flex中创建Accordion报错
  9. table中强制不换行
  10. Unity3D案例太空射击(Space Shooter)流程介绍与代码分析(中)
  11. 2022陈箫箫胡程灿信息论课程作业 MIMO信道(multi-input multi-output,MIMO)简介
  12. 强劲大小核结构 三星将推八核处理器
  13. 医咖会免费SPSS教程学习笔记—Cohen’s kappa系数
  14. ADC分类及主要技术指标
  15. P3386 【模板】二分图最大匹配(匈牙利算法,网络流)
  16. 基于stm32+LM2904+esp8266的噪声预警系统(续集)
  17. Android开发学习之基于ZBar实现微信扫一扫
  18. 【离散椭圆弧】将椭圆弧按弧长等分为一定数量弧上点
  19. apicloud (第五篇 bmap百度地图一键回到当前位置)
  20. AT89C51单片机的抢答器的设计(2位一体共阳)

热门文章

  1. 腾讯回应微信刷掌支付;iPhone 13 Pro或提供1TB版本;Git 2.33 发布|极客头条
  2. html5自定义变量,javascript中怎么定义全局变量?
  3. 软件测试 实验三 白盒测试流程图及测试用例设计
  4. typescript中设置别名paths
  5. 每天学一点新知识|提高自己的技能 爬取QQ音乐
  6. WPF基础-DataGrid
  7. python异步教程_【Python 异步编程入门】
  8. 图论8 并查集深入解析——边带权并查集和拓展域并查集和最小生成树
  9. 2018最新云课堂数据分析师完整版
  10. 放大招----软件管理信息列表