接收数据实时更新的波状曲线图

2019-09-26 15:18:05 浏览数 (1)

前面做了一个心电图的demo 心电图,结果发现那个心电图是静态的,是应用一启动就已经画好了的,整个页面向左滑动而已

下面我改造了一下,写了一个实时接收数据的动态心电图,网上其他地方也有,但是没有讲到重点

我们先看看效果图

很符合要求吧?只不过我没有到达屏幕的最右边就开始向左滑动是为了理解更方便

其实图中的波状曲线并不是在右边一个一个的增加,而是数据增加,每次都全部重绘的一遍而已,看起来的效果就像右边在增加一样,这点要理解

先看代码

代码语言:javascript复制
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity">
    <View        android:layout_width="match_parent"        android:layout_height="300dp"        android:background="#000000" />
    <com.jinke.path.PathView        android:id="@ id/pathView"        android:layout_width="match_parent"        android:layout_height="300dp" /></RelativeLayout>
代码语言:javascript复制
import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;
import java.util.Timer;import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
    private Timer timer;    private TimerTask timerTask;
    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        final PathView pathView = findViewById(R.id.pathView);        //模拟实时数据        timer = new Timer();        timerTask = new TimerTask() {            @Override            public void run() {                Log.i("BLE", "11111111111111111");                pathView.setData(-100);            }        };        timer.schedule(timerTask, 0, 1000);    }
    @Override    protected void onDestroy() {        super.onDestroy();        timerTask.cancel();        timer.cancel();        timerTask = null;        timer = null;    }}
代码语言:javascript复制
import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.util.AttributeSet;import android.util.Log;import android.view.View;
import java.util.ArrayList;import java.util.List;
public class PathView extends View {    //画笔    protected Paint paint;    //心电图折线    protected Path path;    //自身的大小    private int width, height;
    int tmpX;    //折现的颜色    private int lineColor = Color.parseColor("#76f112");
    private List<Integer> list = new ArrayList<>();
    public PathView(Context context) {        this(context, null);    }
    public PathView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }
    public PathView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        paint = new Paint();        path = new Path();    }
    private void drawPath(Canvas canvas) {        Log.i("BLE", "drawPath");        // 重置path        path.reset();        paint.reset();        tmpX = 0;        path.moveTo(tmpX, height / 2);        //调节好每个波的X轴距离,尽量和滑动的速度保持一致        for (int i = 0; i < list.size(); i  ) {            path.lineTo(tmpX   50, height / 2   list.get(i));            path.lineTo(tmpX   100, height / 2);            tmpX  = 100;        }        Log.i("BLE", "TMP="   tmpX);        //设置画笔style        paint.setStyle(Paint.Style.STROKE);        paint.setColor(lineColor);        paint.setStrokeWidth(5);        canvas.drawPath(path, paint);    }
    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        width = w;        height = h;        super.onSizeChanged(w, h, oldw, oldh);    }
    @Override    protected void onDraw(Canvas canvas) {        Log.i("BLE", "onDraw");        drawPath(canvas);        //x轴滑动速度,一开始不滑动,当波形图到达最右边的时候开始滑动        if (list.size() > 15) {            scrollBy(1, 0);        }    }
    public void setData(int data) {        Log.i("BLE", "");        //定期删除历史数据,防止图片过长导致崩溃        if (list.size() > 30) {            for (int i = 0; i < 15; i  ) {                list.remove(i);            }            scrollTo(0, 0);        }        list.add(data);        Log.i("BLE", "list-size="   list.size());        postInvalidate();    }}

自定义View大家都会写,关键是如何让这个自定义View不停的动态重绘呢,网上没有一个说明白的,我来告诉大家

重点:

1.MainActivity里的pathView.setData(-100);方法调用了PathView的setData方法,并传入了更新的值

2.PathView调用了postInvalidate方法,触发重绘

另外在开发中还遇到一个,就是当数据量比较大,View一直向左边滑动,到了某一个时刻,波状图会消失,一片漆黑,看报错原因,是因为滑动的太久,图片拉伸太长导致,手机系统对于长图有一个最长像素值,超过了这个值就会出问题

那么我是如何解决的呢?

1.当数据到达一定量的时候,删掉一部分历史的数据

2.删的同时通过scrollTo(0, 0)方法瞬间滑动最左边

这样就相当于一直在一个固定长度的View上绘图,就不会出问题了,只不过会有少许的偏差,可以调节到滑动的速度和每个波图的X轴距离尽可能的让用户感觉不到

GitHub地址:https://github.com/king1039/Path

0 人点赞