android 绘制心电波形图

public class RealTimeWaveView extends SurfaceView {
    private static String TAG = RealTimeWaveView.class.getSimpleName();
    private SurfaceHolder surfaceHolder;
    private Paint paint = new Paint();
    private int width; // view width
    private int height; // view height
    private final int yMax = 300; // Y轴默认最大值

    private BlockingQueue queue = new LinkedBlockingDeque<>();

    private ScheduledExecutorService scheduledExecutorService;

    private long startDrawDelay = 3 * 1000; // 延迟 3 秒开始绘图

    private float clearGap = getResources().getDimension(R.dimen.clear_gap);

    private Canvas drawCanvas, clearCanvas;
    private Bitmap drawBitmap, clearBitmap;

    public void putData(String valuesArray) {
        JSONArray jsonArray = JSON.parseArray(valuesArray);
        for (int i = 0; i < jsonArray.size(); i++) {
            Integer v = jsonArray.getInteger(i);
            queue.offer(v);
        }
    }

    public RealTimeWaveView(Context context) {
        super(context);
        init();
    }

    public RealTimeWaveView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        paint.setColor(Color.GREEN);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(2);
        paint.setAntiAlias(true);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeJoin(Paint.Join.ROUND);

        surfaceHolder = getHolder();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                MyLogger.d(TAG, "surfaceCreated");
                scheduledExecutorService = Executors.newScheduledThreadPool(5);
                scheduledExecutorService.scheduleAtFixedRate(new DrawRunnable(), startDrawDelay, 40, TimeUnit.MILLISECONDS);
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                MyLogger.d(TAG, "surfaceDestroyed");
                scheduledExecutorService.shutdown();
            }
        });
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
        MyLogger.d(TAG, "width " + width + " height " + height);
        drawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        drawCanvas = new Canvas(drawBitmap);
        drawCanvas.drawColor(getResources().getColor(android.R.color.black));
        clearBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        clearCanvas = new Canvas(clearBitmap);
        clearCanvas.drawColor(getResources().getColor(android.R.color.black));
    }

    class DrawRunnable implements Runnable {
        float currentX = 0, currentY = height / 2.0f;
        float lastX = 0, lastY = height / 2.0f;
        float deltaX = (float) width / 750;
        int step = 10; // 每次画几个点

        private void drawOne(Canvas canvas) {
            Integer value = queue.poll();
            if (value == null) {
                value = 0;
            }

            currentY = (float) value / yMax * (height / 2.0f) + (height / 2.0f);

            if (currentY > height / 2.0f) {
                currentY = height / 2.0f;
            }

            MyLogger.d(TAG, "x:" + currentX + " y:" + currentY);

            canvas.drawLine(lastX, lastY, currentX, currentY, paint);

            lastX = currentX;
            lastY = currentY;

            currentX += deltaX;
            if (currentX >= width) {
                currentX = 0;
//                currentY = height / 2.0f;
                lastX = 0;
                lastY = height / 2.0f;
            }
        }

        @Override
        public void run() {
            Rect rect = new Rect((int) lastX, 0, (int) (currentX + clearGap), height);
            drawCanvas.drawBitmap(clearBitmap, rect, rect, paint);

            for (int i = 0; i < step; i++) {
                drawOne(drawCanvas);
            }

            Canvas canvas = surfaceHolder.lockCanvas();
            if (canvas != null) {
                canvas.drawBitmap(drawBitmap, 0, 0, paint);
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
}

参考网上思路写的一个 demo,仅供参考
两个 Bitmap 一个作为橡皮檫在前面每次擦除一段比如 20cm,另外一个 Bitmap 在后面每次画一小段比如 15cm, 中间留一个间隔。

假如界面上始终显示 3秒的波形图,假设每一秒给你 100 个点的数据,那么我 3秒内要画 300 个数据点(1秒要画 100 个点)。
然后根据 view 的宽度就能得到每两个点的间隔 deltaX, 然后 x轴 从零开始间隔 deltaX 画一点就行了,画到头再从头循环。

我 1 秒要画 100 个点,也就是 10毫秒要画一个点(一个线段)。如果一次画一个点界面上划线速度太慢,我们可以一次画多个点(多条线段),比如我可以每次画 10 个点,要在 100毫秒内画完 10 个点(9条线段)。 然后划线时间可以用定时器控制,每隔100毫秒定时器执行一次绘制,绘制 10 个点的数据(这里忽略绘制时间,假设10个点肯定可在100毫秒内画完)。

你可能感兴趣的:(android 绘制心电波形图)