canvas教程

分析实现Android自定义View之递增直方图

字号+ 作者:H5之家 来源:H5之家 2017-01-01 17:05 我要评论( )

分析实现Android自定义View之递增直方图

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

itdadao


运行图^_^ 1 从分析最终效果 2 再分析,要在屏幕上画这样的竖直列,怎样画?

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

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

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

drawPoint 画点 drawLine 画直线

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

确定了,就用drawLine来试试

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

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

于是肯定就需要一个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 = ; this.name = name; } } 4 结合Android的屏幕坐标,分析:
  • Andriod屏幕的坐标系统默认是左上角为原点,正方向x轴向右,y轴向下
  • View的画布(canvas)的坐标系统默认和屏幕的一样
  • itdadao


    屏幕和画布坐标.png

    而直方图的坐标系是以左下角为原点,所以首先就要获取直方图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轴方向是相反的,所以后面有关坐标的计算需要注意

    itdadao


    坐标注意.png

    如图:计算每列直方图的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 = (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 = (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还有很长的路要走

    完整代码请移步

    Tags:程序员   Android知识   今日看点

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • 程序员技术练级攻略

      程序员技术练级攻略

      2016-11-02 11:00

    • HTML5学习记录-----canvas学习之鼠标选取放大图像

      HTML5学习记录-----canvas学习之鼠标选取放大图像

      2016-03-10 19:41

    • HTML5学习记录-----canvas学习动画快照

      HTML5学习记录-----canvas学习动画快照

      2015-11-21 19:51

    • Java开发 程序员之家论坛

      Java开发 程序员之家论坛

      2015-11-11 14:58

    网友点评