前言

  本文将介绍股票K线图的实现方案,项目名为KLineChart,github地址https://github.com/zengzg/KLineChart。

介绍

  K线图一般分为日K、周K、月K,显示的内容有开/收盘价、最高/低价、成交量,额外信息为均线(ma5/10/20)。例如,日K图中就为当日开/收盘价、最高/低价、成交量和5/10/20日均线。K线图支持滑动,滑动过程中,动态改变最高最低价(和成交量);放大缩小可以由两根手指触发,双击也可以放大K线图;节点应该由右向左按时间倒序分布,支持“加载更多”。
  无论是日K还是周K、月K显示的内容的模型其实是一样,只是采样周期不同,所以节点可以封装为同一个,名为Entry,包含属性:open、close、high、low、volume、ma5、ma10、ma20。显然K线图会同时显示多个节点,那就封装为EntryData,除了封装有一个节点集合外,还封装了对集合的所有相关操作,比如计算最大最小价、添加节点等。为了方便使用,可以将K线图做成一个自定义控件,并且可以将所有绘制工作封装在一起,名为Renderer,这个控件名当然就叫KLineChart了,由于滑动相关的实现与Android触摸事件处理息息相关,所以就写在KLineChart类中了。

详细设计

  我不打算将每行代码都在这篇文章中一一细说,本文就实现中的2个重点作讲解,具体代码大家可以去查看源码。
  首先要说的第一点就是绘制Entry。对于Entry的绘制,难点在于坐标映射,也就是说要将Entry集合一一计算出最终在canvas上绘制的坐标。这种映射逻辑可以用3个Matrix表示,下面我一一说明这3个Matrix的作用。
  value matrix:坐标映射的第一步是将所有节点均匀分布在整个canvas绘制区域内。对于x轴,我们要计算的只是拉伸量,可以用width/entrise.size表示,entrise表示的就是Entry集合;对于y轴,除了拉伸量外还有个平移量,这是因为所有节点的Y值并不是从0开始的,可以用height/yValueRange表示,yValueRange就是所有节点的Y值区间(最大值-最小值);最后由于要实现从右到左分布节点,而且要y值越小的y坐标越大,可以将拉伸量设置为负数,并平移width(height)距离:

mMatrixValue.postTranslate(0, -yMin);
mMatrixValue.postScale(-scaleX, -scaleY);
mMatrixValue.postTranslate(rect.width(),rect.height());

这样value matrix就设置完成了,下面给张图帮助理解:

  touch matrix:通过上面的value matrix变换后,我们就可以把当前集合中的所有节点映射到canvas上了,下一步拉伸(并平移)上面映射出的图形,因为往往一屏并不能显示出所有节点,为了支持滑动或者说当集合元素个数大于我们设置可绘制节点数时,就要对上一步变换后的图形作拉伸,x轴拉伸量可以用entries.size/drawCount表示,drawCount就是我们设置的可绘制节点数量:

 mMatrixTouch.postScale(scaleX, scaleY);minTouchOffset = 0;maxTouchOffset = candleRect.width() * (scaleX - 1f);mMatrixTouch.postTranslate(-maxTouchOffset, 0);

其中y轴不需要拉伸,所以scaleY取1。有了这个x轴的拉伸量后,也就可以计算出x轴的最大最小平移量了,如上代码所示。下面给张图帮助理解:

  offset matrix:这个matrix相对来说较为简单,它的作用是上面变换后的图形作平移,空出绘制y轴和x轴的区间。

mMatrixOffset.postTranslate(offsetX, offsetY);

这个平移大小y轴并没有特殊限制了,而x轴的平移大小应该和y值的绘制区间相关。下面给张图帮助理解:

  通过上面3个矩阵变换后就可以得到最终的绘制点了,其实这本可以用1个矩阵来表示的,之所以分成3个最主要的原因是滑动过程中,我们只需要更新touch matrix的x轴的平移量便可,而平移的变化量自然就是由手指滑动距离来计算的了。
  下面就开始介绍实现中的另一个难点了——滑动。与RecyclerView相同,定义滑动分为2部分scroll与fling,其中scroll是由触屏事件ACTION_MOVE触发的,fling是由触屏事件ACTION_UP触发的。
  我们先通过ViewConfiguration获得启动滑动的最小位移量,名为touch slop,这个常量的用法是:当滑动偏移量首次大于这个值时,之后的ACTION_MOVE事件,才能识别为用户滑屏事件。当将ACTION_MOVE视为滑屏事件时,计算滑动偏移量dx,然后将这个偏移量作为x轴的平移增量更新touch matrix:

mMatrixTouch.getValues(matrixValues);matrixValues[Matrix.MTRANS_X] += -dx;
matrixValues[Matrix.MTRANS_Y] += dy;if (matrixValues[Matrix.MTRANS_X] < -maxTouchOffset) {matrixValues[Matrix.MTRANS_X] = -maxTouchOffset;
}
if (matrixValues[Matrix.MTRANS_X] > 0) {matrixValues[Matrix.MTRANS_X] = 0;
}mMatrixTouch.setValues(matrixValues);

这样再通过3个matrix变换后得到的Entry坐标就是我们滑动过后的新坐标,最后重绘UI。
  fling的滑动是借助Scroller类实现的。捕获ACTION_UP事件,通过VelocityTracker类计算得到事件触发时的滑动初速度,在K线图中只用处理x轴的即可,这个初速度我命名为velocityX,对velocityX作边界检测,这个很好理解,速度不能太快或太慢,边界值或叫阀值同样可以通过ViewConfiguration获得;因为fling是一个自发的连续性动画,方法View.postOnAnimation(Runnable)可以使给定的Runnable对象在下一帧绘制时执行,我们可以利用这个机制,来实现一个“类递归”功能,以驱动fling的“自发及连续性”,将这个功能封装在类ViewFlinger中:

class ViewFlinger implements Runnable{public void run{final int x = scroller.getCurrX();final int y = scroller.getCurrY();final int dx = x - mLastFlingX;final int dy = y - mLastFlingY;mLastFlingX = x;mLastFlingY = y;scroll(dx, 0);if (!scroller.isFinished()) {postOnAnimation();}}public void fling(velocityX,velocityY){scroller.fling(0,0,velocityX,velocityY,...);postOnAnimation();}
}

上面就是ViewFling中的关键代码了,可以看出方法fling()就是触发这个“类递归”执行的地方,然后在这个Runnable执行过程中,调用的scroll()方法其实就是上文所讲的scroll过程中更新touch matrix并重绘UI的方法,只是给定的x轴平移增量是由Scroller计算得到的。至此K线图实现的2个难点就讲完了,如有不对,欢迎指正。最后再给张相对完整的演示图:

结束语

  在实现基本的K线图功能中,对于坐标映射与滑动这2个难点的实现方案,其实并不是我想出来的。其中,坐标映射的方案来自开源项目MPAndroidChart,而滑动的方案取自RecyclerView。这就叫学以致用:)

Written with StackEdit.

Android版股票K线图实现方案相关推荐

  1. 利用JFreeChart绘制股票K线图

    因为工作的需要,接触了一些股票图形绘制类的工作,其中最主要的还是股票K线图的绘制了,如果利用编程语言最底层的图形绘制方法去绘制这类图形,如果对编程语言不是特别熟悉的话,一般是有很大的困难的,通过在网上 ...

  2. layui + echarts股票K线图(含案例、代码、截图)(转载篇)

    文章目录 layui + echarts股票K线图(含案例.代码.截图)(转载篇) 一.案例.代码.截图 经验 · 补充说明: layui + echarts股票K线图(含案例.代码.截图)(转载篇) ...

  3. java绘制均线图_利用JFreeChart绘制股票K线图完整解决方案

    因为工作的需要,接触了一些股票图形绘制类的工作,其中最主要的还是股票K线图的绘制了,如果利用编程语言最底层的图形绘制方法去绘制这类图形,如果对编程语言不是特别熟悉的话,一般是有很大的困难的,通过在网上 ...

  4. 数据可视化7_股票K线图

    文章目录 题目要求 数据源 代码 简单版 复杂版 遗忘的知识 1. numpy 2. json和python数据转换 题目要求 excel里的股票数据搞成K线图 数据源 阿里巴巴2020年股票数据.x ...

  5. 如何使用Tushare和Echarts来画股票K线图

    如何使用Tushare和Echarts来画股票K线图 技术支持 Tushare大数据社区官网 ​ 首先介绍一下这次要使用的两个工具,Tushare是一个基于Python的金融数据接口,拥有丰富的数据内 ...

  6. plotly基于dataframe数据绘制股票K线图并过滤非交易时间

    plotly基于dataframe数据绘制股票K线图并过滤非交易时间 #ohlc过滤非交易时间: import plotly as py # 导入plotly库并命名为py import plotly ...

  7. dax和m的区别_动态股票K线图----从M语言到DAX表达式

    偶然见别人画的股票K线图,不禁见猎心喜,也来模仿一番.原图是不能动的,一动MACD移动平滑趋势线就没有了.这是微软excel的一个缺陷. 所以我想了一个办法弥补这个缺陷.由于手头没有数据,开始实施网抓 ...

  8. Python绘制股票K线图

    目录 1 股票K线图知识了解 2 用Python绘制股票K线图 2.1 安装绘制K线图的mpl_finance库 2.2 引入相关库 2.3 用Tushare库获取股票基本数据 2.4 日期格式调整及 ...

  9. 利用 python numpy +matplotlib 绘制股票k线图

    一.python numpy + matplotlib 画股票k线图 # -- coding: utf-8 -- import requests import numpy as np from mat ...

最新文章

  1. hadoop集群_Ambari搭建hadoop集群
  2. 谈谈Java中的volatile
  3. 2018-2019-2 网络对抗技术 20165337 Exp4 恶意代码分析
  4. 品牌网络推广方案浅析网站改版时如何更好地规避降权风险?
  5. 使用Navicat创建数据库,外键出现错误ERROR 1005: Can't create table (errno: 121)
  6. [python Cookbook]阅读笔记
  7. SAP Cloud for Customer里的Sales Lead和Lead
  8. SpringBoot2.x Flowable 6.4.2 开源项目
  9. 哈弗F7x驾舱数字化测试 语音识别精准
  10. 如何运行wifi服务器,技术:如何通过wifi进行文件传输?
  11. [转载] python 命名空间
  12. html项目组成员分工情况,分工.html · zhongjingxin/APP_I组_期末项目PRD文档 - Gitee.com...
  13. 【预测模型】基于VMD结合Elman神经网络预测数据matlab代码
  14. C primer plus 第六版pdf下载
  15. 观察者模式和模拟wow插件的例子
  16. 地震数据剖面图-matlab
  17. 小红书心灵捕手招募令,百亿流量扶持优质情感主播!
  18. 【洛谷 2958】木瓜的丛林
  19. VIN码识别-汽修行业新技术
  20. win10误禁用任务计划程序导致任务栏里的输入法丢失

热门文章

  1. js中几种对数值取整数和小数部分的方法
  2. 将数字编号翻译为英文编号(python)实现
  3. Nacos服务端ip地址修改
  4. windows下使用控制台打开conda虚拟环境
  5. java I/O流
  6. unity 下载图片使用并保存在本地
  7. Html5 Egret游戏开发 成语大挑战(八)一般性二级页面处理
  8. 本地管理表空间(LMT)与自动段空间管理(ASSM)概念(未看)
  9. 为何一个简单的测试类H5却要花费我2天时间才完成?
  10. 【产品经理学习笔记 | 巨详细】2.规划阶段——2.1需求收集:用户访谈和问卷调查方式