继上次分析实现Android自定义View之扇形图之后,自己又画了下面的这个递增直方图,本来是想做个静态的直方图就完了,结果想想静态的没啥趣味,于是就加了递增

1 从分析最终效果

  1. 界面上要展现的东西有:x和y两个坐标轴
  2. 主角直方图每列
  3. 直方图顶部文字

2 再分析,要在屏幕上画这样的竖直列,怎样画?

在屏幕上画图就是给指定的屏幕坐标点上色

于是就想到只要能给出每列起始坐标高度的终点坐标,然后给起点和终点之间的点全部上色,最终就应该能有这样的效果

接着去看我们的绘画师(canvas)有哪些工具能给我使用,找到有这两个工具,可能可以给我们使用

 drawPoint 画点
drawLine 画直线

再想想刚才想的:把起点和终点之间的点全部上色,不就是在起点和终点之间画一条直线嘛,想把线画成像直方图,可以直接把画笔调粗点不就可以了

确定了,就用drawLine来试试

3 接着把界面上的元素转换为数据

看看每列直方图有哪些属性:

  1. 最明显:颜色 color
  2. 顶上的描述:name
  3. 底部的位置应该用x轴坐标来描述吧:x
  4. 每列的高度:y

于是肯定就需要一个bean来存放每列直方图的数据

public class HistogramData {
public int value; //数值
public String name; //文字描述 public float persentage; //占数据总数的百分比
public float y; //在直方图上的x轴坐标
public float x; //在直方图上的y轴坐标
public int color; //填充颜色 public HistogramData(int value, String name) {
this.value = value;
this.name = name;
}
}

4 结合Android的屏幕坐标,分析:

  1. Andriod屏幕的坐标系统默认是左上角为原点,正方向x轴向右,y轴向下
  2. View的画布(canvas)的坐标系统默认和屏幕的一样

直方图的坐标系是以左下角为原点,所以首先就要获取直方图View画布在屏幕中的尺寸,然后找到左下角的点作为直方图的原点

获取View在屏幕中的尺寸,只需在onSizeChanged中就可以得到

protected void onSizeChanged(int w, int h, int oldw, int oldh){
super.onSizeChanged(w, h, oldw, oldh);
this.w = w - 10;
this.h = h - 10;
}

这里减去10,是为了让直方图原点距离画布编辑有一定间隔

由于画布坐标和直方图坐标的y轴方向是相反的,所以后面有关坐标的计算需要注意

如图:计算每列直方图的y轴坐标时,就需要通过( h - 列高度 )来得到,使用drawLine画线时还是这样

canvas.drawLine(histogramData.x, h, histogramData.x, histogramData.y,paint);

竖直方向是画从h到y的直线,而不是从0到y的直线

5 具体实现

通过上面的分析,基本上已经可以开始画直方图了

会用到的变量

private int[] mColors = {Color.BLUE, Color.DKGRAY, Color.CYAN, Color.RED, Color.GREEN};
private ArrayList<HistogramData> datas;
private Paint paint; //画笔
private int mWidth = 70; //直方图宽
private int width2 = 20; //直方图间距
private int w; //画布宽
private int h; //画布高

在onSizeChanged方法里确定了画布宽高之后,就会走到onDraw里开始画画

画直方图坐标

paint.setColor(Color.BLACK);
paint.setStrokeWidth(5);
canvas.drawLine(10, h, w, h, paint); //画坐标系X轴
canvas.drawLine(10, h, 10, 10, paint); //画坐标系Y轴

画每列直方图

paint.setStrokeWidth(mWidth);
paint.setStyle(Paint.Style.STROKE);
if (null == datas) {
return;
}
for (int i = 0; i < datas.size(); i++) {
HistogramData histogramData = datas.get(i);
paint.setColor(histogramData.color);
canvas.drawLine(histogramData.x, h, histogramData.x, histogramData.y,paint); //直方图顶部文字
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
canvas.drawText(histogramData.name, histogramData.x - mWidth / 4, histogramData.y - 10, paint);
}

6 实现递增

递增的实现主要是在数据处理的时候加上了线程和handler

public void setData(ArrayList<HistogramData> data) {
this.datas = data;
if (null == datas || datas.size() == 0) {
return;
}
myHandler = new MyHandler(this);
new Thread(new Runnable() {
@Override
public void run() {
//计算数据总和
float sum = 0;
for (int i = 0; i < datas.size(); i++) {
sum += datas.get(i).value;
}
//计算数据占总数的百分比
for (int i = 0; i < datas.size(); i++) {
HistogramData histogramData = datas.get(i);
histogramData.persentage = histogramData.value / sum;
}
//计算单列数据高度,并缓慢增加
float startX, endY;
for (int i = 0; i < datas.size(); i++) {
HistogramData histogramData = datas.get(i);
startX = (i + 1) * mWidth + i * width2;
endY = HistogramView.this.h - histogramData.persentage * HistogramView.this.h;
histogramData.color = mColors[i % mColors.length];
//注意:画布的坐标是左上角为原点,所以是
// 从 画布高-10 为起点, 数据高度 为终点
// 递减
for (int j = HistogramView.this.h; j >= endY; j--) {
histogramData.x = startX;
histogramData.y = j;
//通知UI更新
myHandler.sendEmptyMessage(0);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}

最终效果就是上面那(cu)张(cao)GIF了_,自定义View还有很长的路要走

完整代码请移步

Android直方图递增View的更多相关文章

  1. Android 判断一个 View 是否可见 getLocalVisibleRect(rect) 与 getGlobalVisibleRect(rect)

    Android 判断一个 View 是否可见 getLocalVisibleRect(rect) 与 getGlobalVisibleRect(rect) [TOC] 这两个方法的区别 View.ge ...

  2. 1.Android 视图及View绘制分析笔记之setContentView

    自从1983年第一台图形用户界面的个人电脑问世以来,几乎所有的PC操作系统都支持可视化操作,Android也不例外.对于所有Android Developer来说,我们接触最多的控件就是View.通常 ...

  3. Android读取自定义View属性

    Android读取自定义View属性 attrs.xml : <?xml version="1.0" encoding="utf-8"?> < ...

  4. android中实现view可以滑动的六种方法续篇(二)

    承接上一篇,上一篇中讲解了实现滑动的第五种方法,如果你还没读过,可点击下面链接: http://www.cnblogs.com/fuly550871915/p/4985482.html 这篇文章现在来 ...

  5. Android点击View显示PopupWindow,再次重复点击View关闭PopupWindow

     Android点击View显示PopupWindow,再次重复点击View关闭PopupWindow 这本身是一个看似很简单的问题,但是如果设置不当,就可能导致莫名其妙失效问题.通常在Andro ...

  6. Android Touch(3)View的touchDelegate

    作用: 基类View有个函数 public void setTouchDelegate(TouchDelegate delegate),给view内部的另一个view设置一个touch代理. 图中vi ...

  7. Android 自己定义View (二) 进阶

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24300125 继续自己定义View之旅.前面已经介绍过一个自己定义View的基础 ...

  8. ViewPager空指针错误,android.support.v4.view.ViewPager.onSaveInstanceState

    support.v4 包为我们提供了一个非常实用的滑动控件ViewPager,在使用ViewPager时有一个需要注意的地方: 即: android.support.v4.view.ViewPager ...

  9. Android轶事之View要去大保健?View大小自己决定?

    -"爹,我要吃糖" -"好哒儿子" -"爹,我要吃包包" - "好哒儿子" - "爹,我要吃串串" ...

随机推荐

  1. DDD:一个朋友对领域驱动的小结

    首先我在一家老板有点关系的小软件公司带领一帮工作一两年的程序员做项目,这里要特别强调的是做项目(差不多是外包,只不过客户群体比较固定),项目就是今天项目A是这个逻辑,明天项目B是那个逻辑,两者之间的业 ...

  2. 介绍WEB站点结构

    在这节里,我们将抛开Umbraco来看看已创建的站点.在我们介绍Umbraco之前,需要了解站点是如何工作的,如何使用使用浏览器工具. 我们看到在标签顶端的内容叫做页面标题.每个页面的标题都会改变表示 ...

  3. 数据可视化(4)--jqplot

    本来打算继续研究Google Charts,但上头下了指示让看jqplot,无奈,只好先将Google Charts放一放,不过真心觉得Google Charts不错,现在先开始jqplot. jqP ...

  4. @import和link的区别

    @import和link的区别 1.link语法结构    <link href="CSSurl路径" rel="stylesheet" type=&qu ...

  5. CentOS6.5菜鸟之旅:安装ATI显卡驱动

    一.前言 自从安装了CentOS,我的显卡就没消停过,一直在彪高温而且噪音特别大,于是决定上网搜索解决办法.下面记录下来以供日后查阅. 二.安装fglrx driver(ATI/AMD 显卡的linu ...

  6. Python+Selenium进行UI自动化测试项目中,常用的小技巧4:日志打印,longging模块(控制台和文件同时输出)

    在前段时间,为了给项目中加入日志功能,就想到了 logging 模块,百度logging一大推,都是各种复制的,并没有找到自己想要的结果:我的目的很简单,就是:在把日志写入文件的同时在控制台输出,更加 ...

  7. Sprint Three 回顾与总结&发表评论&团队贡献分

    ● 一.回顾与总结 (1)回顾 燃尽图: Sprint计划-流程图: milestones完成情况如下: (2)总结 从sprint one到three,我们团队配合十分默契,互相帮助,虽然遇到了不少 ...

  8. 判断Integer值相等最好不用==(未整理)

    今天在开发中判断两个Integer值相等, Integer a = 3; Duixiang duixiang = new Duixiang(); duixiang = DAO.getDuixiang( ...

  9. [新手学Java]使用beanUtils控制javabean

    使用BeanUtils设置/读取属性的值以及默认支持的自动转化: @Test //使用BeanUtils设置/读取属性的值以及自动转化 public void test1() throws Illeg ...

  10. LeetCode2:Median of Two Sorted Arrays

    题目: There are two sorted arrays A and B of size m and n respectively. Find the median of the two sor ...