在上篇Android——ECG心电图的绘制实现博客中,实现了心电图的数据展示绘制。

在之后又新增了 心电图的自动滑动展示 实时绘制 功能。效果如下:

自动滑动展示

实时绘制(这里用到了一个timer不断添加数据)

一、自动滑动展示 实现

实现思路:

通过开启定时器实现下标scrollIndex不断增加,以此来计算展示数据的开始下标scrollStartIndex与结束下标scrollEndIndex,来获得一段数据data[]中的展示数据,该段数据刚好填满view的宽度(按比例填满),然后不断的更细视图,实现视觉上的滑动效果(View实际上没有滑动)。如图所示:

代码实现:

首先在initData()初始化数据的时候,调用startScrollTimer()方法,开启一个timer,去不断的更新下标:

    private fun startScrollTimer() {        timer = Timer()        timerTask = object : TimerTask() {            override fun run() {                if (scrollIndex < data!!.size) {                    scrollIndex++                } else {                    scrollIndex = 0                }            }        }        timer!!.schedule(timerTask, 0, 50)    }

然后在ondraw中,进行具体的绘制:

// 绘制心电滚动视图    private fun drawHeartScroll(canvas: Canvas) {        if (data == null || data!!.size == 0) {            return        }        paint!!.reset()        path!!.reset()        paint!!.style = Paint.Style.STROKE        paint!!.color = Color.parseColor("#31CE32")        paint!!.strokeWidth = mGridLinestrokeWidth        paint!!.isAntiAlias = true        path!!.moveTo(0f, mHeight / 2)        var scrollStartIndex = 0        var scrollEndIndex = 0        scrollEndIndex = scrollIndex        scrollStartIndex = scrollEndIndex - intervalNumHeart        if (scrollStartIndex < 0) {            scrollStartIndex = 0        }        var nowX: Float        var nowY: Float        for (i in scrollStartIndex until scrollEndIndex) {            nowX = (i - scrollStartIndex) * intervalRowHeart            var dataValue = data!![i]            if (dataValue > 0) {                if (dataValue > MAX_VALUE * 0.8f) {                    dataValue = MAX_VALUE * 0.8f                }            } else {                if (dataValue < -MAX_VALUE * 0.8f) {                    dataValue = -(MAX_VALUE * 0.8f)                }            }            nowY = mHeight / 2 - dataValue * intervalColumnHeart            path!!.lineTo(nowX, nowY)            LogUtils.d("drawHeartScroll $nowX $nowY")        }        canvas.drawPath(path!!, paint!!)        postInvalidate()    }

其中,前半部分是对数据下标的整理,后半部分是对整理的data数据进行实时展示。

二、实时绘制刷新refresh 实现

实现思路

这个就比上一个复杂多了。通过showLine(float float) 方法,让外界能输入数据并动态展示在心电图上,也就是说需要实现一个动态递增的Arraylist,然后在具体的绘制中,实现如下所示的数据结构:

第1次添加   1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,                      
第2次添加   1 , 2 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,                      
第3次添加   1 , 2 , 3 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,                      
第4次添加   1 , 2 , 3 , 4 , 0 , 0 , 0 , 0 , 0 , 0 ,                      
第5次添加   1 , 2 , 3 , 4 , 5 , 0 , 0 , 0 , 0 , 0 ,                      
第6次添加   1 , 2 , 3 , 4 , 5 , 6 , 0 , 0 , 0 , 0 ,                      
第7次添加   1 , 2 , 3 , 4 , 5 , 6 , 7 , 0 , 0 , 0 ,                      
第8次添加   1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 0 , 0 ,                      
第9次添加   1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 ,                      
第10次添加   1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ,                      
第11次添加   11 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ,                      
第12次添加   11 , 12 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ,                      
第13次添加   11 , 12 , 13 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ,                      
第14次添加   11 , 12 , 13 , 14 , 5 , 6 , 7 , 8 , 9 , 10 ,                      
第15次添加   11 , 12 , 13 , 14 , 15 , 6 , 7 , 8 , 9 , 10 ,                      
第16次添加   11 , 12 , 13 , 14 , 15 , 16 , 7 , 8 , 9 , 10 ,                      
第17次添加   11 , 12 , 13 , 14 , 15 , 16 , 17 , 8 , 9 , 10 ,                      
第18次添加   11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 9 , 10 ,                      
第19次添加   11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 10 ,                      
第20次添加   11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 ,                      
第21次添加   21 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 ,                      
第22次添加   21 , 22 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 ,                      
第23次添加   21 , 22 , 23 , 14 , 15 , 16 , 17 , 18 , 19 , 20 ,                      
第24次添加   21 , 22 , 23 , 24 , 15 , 16 , 17 , 18 , 19 , 20 ,                      
第25次添加   21 , 22 , 23 , 24 , 25 , 16 , 17 , 18 , 19 , 20 ,                      
第26次添加   21 , 22 , 23 , 24 , 25 , 26 , 17 , 18 , 19 , 20 ,                      
第27次添加   21 , 22 , 23 , 24 , 25 , 26 , 27 , 18 , 19 , 20 ,    ....(后面省略)

可以看到要位置一个总长度固定的数据,但是随着数据的增加新的数据是从左往右进行刷新的(对应刷新心电图数据的刷新方式),实现了该结构之后,再去做数据展示就可以实现心电图的刷新绘制了。

为此我专门写了一个测试类去测试:

public class TestClass {    private static List refreshList = new ArrayList<>();    private static float[] data; //一排显示的数据  一排10个    private static int intervalNumHeart = 10;    private static int showIndex;    public static void main(String[] args) {        data = new float[intervalNumHeart];        for (int i = 1; i < 100; i++) {            refreshList.add((float) i);            drawHeartRefresh();        }    }    private static void drawHeartRefresh() {        int nowIndex = refreshList.size(); //当前长度        if (nowIndex < intervalNumHeart) {            showIndex = nowIndex - 1;        } else {            showIndex = (nowIndex - 1) % intervalNumHeart;        }        for (int i = 0; i < intervalNumHeart; i++) {            if (i > refreshList.size() - 1) {                break;            }            if (nowIndex <= intervalNumHeart) {                data[i] = refreshList.get(i);            } else {                int times = (nowIndex - 1) / intervalNumHeart;                int temp = times * intervalNumHeart + i;                if (temp < nowIndex) {                    data[i] =                            refreshList.get(temp);                }            }        }        logdata();    }    private static void logdata() {        String str = "";        for (float temp : data) {            int tempInt = (int) temp;            str += tempInt + " , ";        }        Log( "第" +(refreshList.size()) + "次添加   " + str + "                     " );    }    private static void Log(String txt) {        System.out.println(txt);    }}

代码实现

一样分为两个部分,前半部分实现该结构,后半部分进行具体的绘制:

private fun drawHeartRefresh(canvas: Canvas) {        paint!!.reset()        path!!.reset()        paint!!.style = Paint.Style.STROKE        paint!!.color = Color.parseColor("#31CE32")        paint!!.strokeWidth = mGridLinestrokeWidth        paint!!.isAntiAlias = true        path!!.moveTo(0f, mHeight / 2)        val nowIndex = if (refreshList == null) 0 else refreshList!!.size //当前长度        if (nowIndex == 0) {            return        }        if (nowIndex < intervalNumHeart) {            showIndex = nowIndex - 1        } else {            showIndex = (nowIndex - 1) % intervalNumHeart        }        for (i in 0 until intervalNumHeart) {            if (i > refreshList!!.size - 1) {                break            }            if (nowIndex <= intervalNumHeart) {                data!![i] = refreshList!![i]            } else {                val times = (nowIndex - 1) / intervalNumHeart                val temp = times * intervalNumHeart + i                if (temp < nowIndex) {                    data?.set(i, refreshList!![temp])                }            }        }        logdata()        //绘制出data        var nowX: Float        var nowY: Float        for (i in data!!.indices) {            nowX = i * intervalRowHeart            var dataValue = data!![i]            if (dataValue > 0) {                if (dataValue > MAX_VALUE * 0.8f) {                    dataValue = MAX_VALUE * 0.8f                }            } else {                if (dataValue < -MAX_VALUE * 0.8f) {                    dataValue = -(MAX_VALUE * 0.8f)                }            }            nowY = mHeight / 2 - dataValue * intervalColumnHeart            if (i - 1 == showIndex) {                path!!.moveTo(nowX, nowY)            } else {                path!!.lineTo(nowX, nowY)            }        }        canvas.drawPath(path!!, paint!!)    }

 

 

近期在把所有写过的自定义view(实用性较强的)整理成一个开源框架,Github地址:

https://github.com/jiangzhengnan/UI#ngui

gradle依赖:

compile 'ng.ngui.ngbase:nguilib:0.0.1'

更多相关文章

  1. “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
  2. Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
  3. 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
  4. Android(安卓)Handler的详细介绍
  5. unity调用android语音识别
  6. android 加密 SQLCipher和Conceal
  7. 第一篇博客——从《第一行代码》学习笔记开始
  8. Android中的搜索(search)概述
  9. Android多文件断点续传(一)——数据封装以及界面实现

随机推荐

  1. 开发可统计单词个数的Android驱动程序(3)
  2. Android牟利之道(二)--广告平台的介绍
  3. Android中实现跨进程通信(IPC)的方式(三)
  4. Study on Android【三】--Intent消息传递
  5. Android开发人员终于在“app-构建控制台
  6. 为什么要用Android(安卓)Studio?
  7. Android中显示网络上的图片
  8. android重力感应模拟器sensorsimulator
  9. [置顶] android 数据库版本升级
  10. Android上HDMI介绍(基于高通平台)