接收蓝牙数据实时更新的波状曲线图
2023-09-14 08:59:10 时间
前面做了一个心电图的demo 心电图,结果发现那个心电图是静态的,是应用一启动就已经画好了的,整个页面向左滑动而已
下面我改造了一下,写了一个实时接收数据的动态心电图,网上其他地方也有,但是没有讲到重点
我们先看看效果图
很符合要求吧?只不过我没有到达屏幕的最右边就开始向左滑动是为了理解更方便
其实图中的波状曲线并不是在右边一个一个的增加,而是数据增加,每次都全部重绘的一遍而已,看起来的效果就像右边在增加一样,这点要理解
先看代码
<?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>
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;
}
}
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
欢迎关注我的微信公众号:安卓圈
相关文章
- Kafka+Spark Streaming+Redis实时计算整合实践
- layui如何实现添加数据时关闭页面层,并实时刷新表格数据?
- Hadoop不适合处理实时数据的原因剖析
- 阿里首次披露中台战略:OneData的统一数据标准和实时数据分析是核心
- 关于 大数据+实时计算 的题外话
- EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器功能简介---实时数据统计报表、视频文件上传、点播、分享、集成
- SPSS与Streams的集成实现实时预测
- linux命令中的字符串中间增加指令,例如路径中增加日期变量,实时获取当前的日期
- 【STM32H7的DSP教程】第47章 STM32H7的IIR带阻滤波器实现(支持逐个数据的实时滤波)
- 【STM32F429的DSP教程】第46章 STM32F429的IIR带通滤波器实现(支持逐个数据的实时滤波)
- 【STM32H7的DSP教程】第39章 STM32H7的FIR带通滤波器实现(支持逐个数据的实时滤波)
- 【STM32H7的DSP教程】第38章 STM32H7的FIR高通滤波器实现(支持逐个数据的实时滤波)
- 利用动态图层实现数据的实时显示
- Py之pygame:有趣好玩—利用pygame库实现鱼儿自动实时目标跟踪(附完整代码)
- 视频直播源码在Android端实现1对1音视频实时通话
- 2023计算机毕业设计题目,供大家参考【源码已实现,实时更新】
- 2022数维杯ABC题思路程序实时更新
- rsync+inotify 数据实时同步介绍与 K8s 实战应用
- 【Mysql异构实时同步Oracle】OGG12异构同步mysql到oracle(windows mysql实时同步数据到linux oracle)详细文档