一个自己参考制作出来的心电图,原理很简单,先上图

上面部分是一个view用于显示局部心电图,下面是一个类似进度条的view用于显示全部心电图,当下面的黄色正方形被拖动,上面则会显示正方形所包含区域的局部心电图,起到一个预览的作用。

原理:现将所有数据传入下面的view画出来,再通过监测其ontouch事件,通过正方形的边长计算出其中包含的数据点,并将其取出传入上面的view进行绘图,下面上代码。

这是:上方那个view的代码

package com.healforce.healthapplication.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.healforce.healthapplication.R;

import java.util.ArrayList;
import java.util.List;

public class PulseView extends View
{private int XLength;
    private int XPoint;
    private int XScale = getResources().getDimensionPixelSize(R.dimen.x2);
    private int YLength = getResources().getDimensionPixelSize(R.dimen.x120);
    private int YPoint = getResources().getDimensionPixelSize(R.dimen.x100);
    private int YScale = getResources().getDimensionPixelSize(R.dimen.x2);

    private int MaxDataSize = XLength / XScale;
    private List<Integer> data;
    private int index;

    public PulseView(Context paramContext){this(paramContext, null);
    }public PulseView(Context paramContext, AttributeSet paramAttributeSet){this(paramContext, paramAttributeSet, 0);
    }public PulseView(Context context, AttributeSet attrs, int resId){super(context, attrs, resId);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PulseView, resId, 0);
        XScale = typedArray.getDimensionPixelSize(0, getResources().getDimensionPixelSize(R.dimen.x2));
        YScale = typedArray.getDimensionPixelSize(1, getResources().getDimensionPixelSize(R.dimen.x20));

        typedArray.recycle();

        data = new ArrayList<>();
    }@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();

        XPoint = getResources().getDimensionPixelSize(R.dimen.x10);
        YPoint = height - getResources().getDimensionPixelSize(R.dimen.x10);
        XLength = width - getResources().getDimensionPixelSize(R.dimen.x20);
        YLength = height - getResources().getDimensionPixelSize(R.dimen.x20);

        MaxDataSize = (XLength / XScale);
        Log.i("PUlse",MaxDataSize+"");
    }public void addDataByPC80B(List<Integer> list) {if (data != null && data.size() > 0){data.clear();
        }for (int i = 0; i < list.size(); i++) {data.add(list.get(i));
            postInvalidate();
            if (data.size() >= MaxDataSize) {data.remove(0);
            }}}protected void onDraw(Canvas canvas){super.onDraw(canvas);
        canvas.drawColor(getResources().getColor(R.color.light_gray));
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setAntiAlias(true);
        paint.setColor(getResources().getColor(R.color.yellow));
        //    画y轴
        canvas.drawLine(XPoint, YPoint - YLength, XPoint, YPoint, paint);

        //    画水平格子线
        for (int i = 0; i * YScale <= YLength; i++) {canvas.drawLine(XPoint, YPoint - i * YScale, XPoint + XLength, YPoint - i * YScale, paint);
        }//    画x轴
        canvas.drawLine(XPoint, YPoint, XPoint + XLength, YPoint, paint);
        //    画竖直格子线
        for (int j = 0; j * YScale <= XLength; j++) {canvas.drawLine(XPoint + j * YScale, YPoint, XPoint + j * YScale, YPoint - YLength, paint);
        }paint.setColor(Color.RED);
        paint.setStrokeWidth(2.0F);
        if (data.size() > 0) {//    画搏动折线
            for (int k = 1; k < data.size(); k++){canvas.drawLine(XPoint + (k - 1) * XScale, YPoint - data.get(k - 1), XPoint + k * XScale, YPoint - data.get(k), paint);
            }//    画刷新线
            paint.setColor(getResources().getColor(R.color.light_gray));
            paint.setStrokeWidth(5.0F);
            canvas.drawLine(index * XScale, YPoint - YLength, index * XScale, YPoint, paint);
        }}public void setData(List<Integer> list) {for (int i = 0;i< list.size(); i++){if (data.size() <= MaxDataSize){data.add(list.get(i));
            }else {if (index == MaxDataSize){index = 0;
                }data.set(index, list.get(i));
                index ++ ;
            }postInvalidate();
        }}
}

主要调用setData的方法传入数据,即可完成绘制,关于绘制的相关知识,不懂的可以查找其他资料了解,这里就不多说,绘制的时候调用的postInvalidate方法主要是因为,我这个是运行在一个线程中,当不在线程中时可以使用 Invalidate也能达到效果。该控件可以实时传入数据绘制动态波形图,使用的是常见的刷新方法,放完一图刷一图,做的不是很好看,有待优化

接下来是下面的view的代码,很简单:

public class PC80bSectionView extends View {private List<Integer> data = new ArrayList<>();  //    数据源
    private float width;    //   控件宽
    private float height;   //   控件高
    private PulseView pulseView;
    //    随手指移动的正方形的中心
    private float rec_centerX;
    private float rec_centerY;
    private Rect rect = new Rect();

    public PC80bSectionView(Context context) {this(context,null,0);
    }public PC80bSectionView(Context context, AttributeSet attrs) {this(context, attrs,0);
    }public PC80bSectionView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);

    }/**
     * 画随手指移动的正方形
     * @param canvas
     * @param paint
     */
    private void drawRect(Canvas canvas, Paint paint) {rec_centerY = (height / 2.0F);
        if (rec_centerX < height / 2.0F) {rec_centerX = (height / 2.0F);
        }if (rec_centerX > width - height / 2.0F) {rec_centerX = (width - height / 2.0F);
        }rect.left = ((int) (rec_centerX - height / 2.0F));
        rect.right = ((int) (rec_centerX + height / 2.0F));
        rect.top = ((int) (rec_centerY + height / 2.0F));
        rect.bottom = ((int) (rec_centerY - height / 2.0F));

        canvas.drawRect(rect.left, rect.top, rect.right, rect.bottom, paint);
    }/**
     * 画波形
     * @param canvas
     * @param paint
     */
    private void drawLine(Canvas canvas, Paint paint) {paint.setColor(Color.GREEN);
        if (this.data.size() > 1){for (int i = 1; i < data.size(); i++){//    4500表示每次心电仪传输过来的30秒数据的个数
                canvas.drawLine((i - 1) * (width / 4500.0F), height - (data.get(i - 1)),
                        i * (width / 4500.0F), height - data.get(i), paint);
            }}}public void postData(List<Integer> list) {data.addAll(list);
        postInvalidate();
    }public void clearData() {if ((data != null) && (data.size() > 1)){data.clear();
        }}protected void onDraw(Canvas canvas) {super.onDraw(canvas);
        canvas.drawColor(Color.BLACK);
        Paint paint = new Paint();
        paint.setColor(Color.YELLOW);
        paint.setStrokeWidth(2.0F);

        drawRect(canvas, paint);
        drawLine(canvas, paint);
    }protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        this.width = getMeasuredWidth();
        this.height = getMeasuredHeight();
    }public boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE:rec_centerX = ((int) event.getX());
                invalidate();
                //    每次正方形发生移动计算出其中包含区间并将响应区间数据发送至pulseView显示
                if (pulseView != null) {List<Integer> list = new ArrayList<>();

                    for (int i = 0; i < data.size(); i++) {if ((i >= (int) (rect.left * 4500.0F / width)) && (i <= (int) (rect.right * 4500.0F / width))){list.add(data.get(i) * 10);
                        }}pulseView.addDataByPC80B(list);
                }}return true;
    }public void setPulseView(PulseView pulseView) {this.pulseView = pulseView;
    }
}

核心代码都在ondraw里面,然后是ontouch时间,非常简单

这就是个人自制的一个简单的显示心电图的控件,本人新手想和大家分享一下,觉得有用就看看,要是觉得不好的就麻烦给点改进意见,初来乍到,请大家不吝赐教

Android 自制的一个简单的心电图pulseview相关推荐

  1. 使用Android Studio编写一个简单的音乐盒

    文章目录 一.知识要点 二.xml代码 activity_main.xml 三.java代码 MainActivity.java MusicService.java 四.运行界面展示 五. 源码Git ...

  2. Android动态日志,一个简单的Android日志类

    Android自带的日志类不支持显示文件名和行号,调试时很不方便.而第三方日志库往往又太重.所以自己对Android自带的日志类做了一个简单的封装,主要是调试时使用,不考虑日志丢失和性能问题.日志的输 ...

  3. 【Android】Android studio做一个简单的图片浏览器

    我们现在布局文件中定义一个简单的线性布局容器,代码如下 activity_main.xml <?xml version="1.0" encoding="utf-8& ...

  4. Android 逆向笔记 —— 一个简单 CrackMe 的逆向总结

    温馨提示 请拖动到文章末尾,长按识别「抽奖」小程序. 在我的印象中,懂逆向的,都是大牛,让我们一起来看看下面这位大牛的学习心得. 无意中在看雪看到一个简单的 CrackMe 应用,正好就着这个例子总结 ...

  5. Android Jetpack Compose——一个简单的微信界面

    一个简单的微信界面 简述 效果视频 底部导航栏 导航元素 导航栏 放入插槽 绘制地图 消息列表 效果图 实现 聊天 效果图 实现 气泡背景 联系人界面 效果图 实现 好友详情 效果图 实现 发现 效果 ...

  6. Android:设计一个简单的调查问卷

    设计一个简单的调查问卷,要求用到TextView,Button,CheckBox,RadioButton,EditText等控件 今天写了一个demo,里面用到了常用的布局,以及常用的几种控件,这里调 ...

  7. 用Android Studio设计一个简单个性的登录界面

    一.用到的组件: LinearLaout.TableLayout.FrameLayout.RelativeLout 二.效果图展示: 三.步骤及过程: 1.首先新建一个Project,并在app -& ...

  8. Android开发做一个简单的音乐播放器

    Android开发如何做一个简单的音乐播放器,首先我们先要知道用到的知识点有哪些. 1.MediaPlayer:可以播放本地资源.sd卡内存资源以及网络uri资源,在这里我们播放sd卡上的音乐资源. ...

  9. 使用Android studio做一个简单的网站APP

    1.首先创建一个空白Android项目 2.然后打开项目,切换为Android视图,这时候会看到三个文件夹,分别是manifests.java.res.首先修改res/layout下的activity ...

最新文章

  1. LeetCode题组:第21题-合并两个有序链表
  2. 安装开源在线教育平台edX的一个简单方法
  3. SpringCloud微服务架构,Spring Cloud 服务治理(Eureka,Consul,Nacos),Ribbon 客户端负载均衡,RestTemplate与OpenFeign实现远程调用
  4. SpringBoot基础篇AOP之基本使用姿势小结
  5. html中文乱码_Nginx目录浏览的中文显示问题订正
  6. c语言点按钮弹窗口,【iOS】按钮点击弹窗
  7. 拖拽之路(一):自定义QListWidget实现美观的拖拽样式(拖拽即选中)
  8. 苹果 SwiftUI 踢馆谷歌 Flutter!
  9. python语言继承6.3节例6-1中的person_第6.3节 Python动态执行之动态编译的compile函数...
  10. linux下无法安装VMware的解决方法
  11. Telerik ui kendo for jquery 2022源码版
  12. 这届年轻人为什么都不爱看电视了?
  13. 推荐4个爬虫抓包神器
  14. RGB565的计算颜色表
  15. 广图登陆知网下载资源教程
  16. 5G 核心网 Inter NG-RAN node N2 based handover 信令流程
  17. 点宽与江苏大学建设量化金融实训平台项目
  18. 【用户投稿】优麒麟社区懒人版本(含软件全家桶)一键安装
  19. 02.Android崩溃Crash库之App崩溃分析
  20. P5017 NOIP2018 普及组 摆渡车

热门文章

  1. 夏普复印机最最最详细的驱动安装教程
  2. linux是不是在根目录下安装的软件其它用户就可以使用,[转载]Linux下非root用户如何安装软件...
  3. 国密算法sm3java软实现_国密算法实现
  4. 清华师姐网盘大曝光(整整400集python学习资料,真香)
  5. 用html和js编写黑洞数,python_黑洞数
  6. Macbook pro提示已损坏,无法打开。您应该将它移到废纸篓
  7. Allegro-默认打开空白PCB文件
  8. 区块链赋能供应链,不让中间商赚差价!
  9. 【一、vxWorks6.9】
  10. eagle-eye介绍