一个自己参考制作出来的心电图,原理很简单,先上图
上面部分是一个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主要调用setData的方法传入数据,即可完成绘制,关于绘制的相关知识,不懂的可以查找其他资料了解,这里就不多说,绘制的时候调用的postInvalidate方法主要是因为,我这个是运行在一个线程中,当不在线程中时可以使用 Invalidate也能达到效果。该控件可以实时传入数据绘制动态波形图,使用的是常见的刷新方法,放完一图刷一图,做的不是很好看,有待优化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 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 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(); } } }
接下来是下面的view的代码,很简单:
public class PC80bSectionView extends View { private List核心代码都在ondraw里面,然后是ontouch时间,非常简单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 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 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; } }
这就是个人自制的一个简单的显示心电图的控件,本人新手想和大家分享一下,觉得有用就看看,要是觉得不好的就麻烦给点改进意见,初来乍到,请大家不吝赐教