Koltin实现动态心率曲线

Posted 期待的是什么

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Koltin实现动态心率曲线相关的知识,希望对你有一定的参考价值。

用MPAndroid 实现动态的心率曲线

废话不多说,先上图
上面是实现效果,由于是第一次上传图片,不会发动图,目前就两张图片,

  1. 首先是集成mpchart android,具体集成方式请直接百度就好
  2. 先实现y轴的代码,相关参数设计如下:
leftAxis?.let {
            //是否绘制轴线
            it.setDrawAxisLine(true)
            //设置轴线的颜色
            it.axisLineColor = context!!.resources.getColor(R.color.color_f3f3f3)
            //是否绘制网格线
            it.setDrawGridLines(true) //横的线(与Y轴有关)
            //y轴的线为虚线
            //leftAxis.enableGridDashedLine(10f, 5f, 0f);
            it.gridLineWidth = gridLineWidth
            //设置网格线的颜色
            it.gridColor = context!!.resources.getColor(R.color.color_f3f3f3)
            it.textSize = axisYTextSize
            it.textColor = axisTextColor
            //leftAxis.setSpaceMin(20);
            //leftAxis.setSpaceMax(20);
            //字体距离曲线的位置
            it.xOffset = 6f
            it.yOffset = 0f
            //设置最大值和最小值
            it.axisMinimum = Y_MIN
            it.axisMaximum = Y_MAX
            //y轴坐标点个数
            it.labelCount = yAxisLabelCount

            it.valueFormatter = StepYaxisValueFormat()
        }
        ///右边的y轴///
        rightAxis?.let {
            it.isEnabled = false
            // it.setDrawAxisLine(false)
            // it.spaceMax = 0f
        }

这里主要是把左边和右边的轴线,显示为不显示,如果需要显示请把 isEnable设置为true,即可

3.接下来是x轴的相关参数的设置:

   xAxis?.let {
            //是否绘制网格线
            it.setDrawGridLines(true) //竖的线(与X轴有关)
            //网格线的宽度
            it.gridLineWidth = gridLineWidth
            //网格颜色
            it.gridColor = context!!.resources.getColor(R.color.color_f3f3f3)
            //字体距离曲线的位置
            it.yOffset = 0f
            it.xOffset = 0f
            it.position = XAxis.XAxisPosition.BOTTOM // 设置X轴的位置
            it.setDrawAxisLine(true) //是否显示X轴
            //轴线的颜色
            it.axisLineColor = context!!.resources.getColor(R.color.color_f3f3f3)
            it.textSize = axisXTextSize
            it.textColor = axisTextColor
            //xAxis.setSpaceMin(5);//小于最小值5开始画
            it.spaceMax = 0f //大于最大值10
            it.axisMinimum = 0f //x轴显示的最小值

            //只有不是实时曲线的时候才设置这个值
            // it.axisMaximum = xAxisVisibleValueRange //x轴显示的最大值

            //xAxis.mAxisRange=2f;
            it.setLabelCount(xAxisLabelCount, false)
            it.valueFormatter = StepXAxisValueFormat()
        }

相同的道理,这里是将x轴的相关方法设置为不显示,具体的参数意思,在代码中已经有了注释,到这里我们完成了,相关设置

4.接下来是实现linechart的曲线属性相关设置;

 /**
     * 
     *
     * @return void
     * @time 2021-9-16 17:06:04
     */
    private fun buildOxDataSet(entries: List<Entry>, label: String): LineDataSet {
       
        val oxDataSet = LineDataSet(entries, label)
        oxDataSet.lineWidth = lineWidth
        oxDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER //设置为贝塞尔曲线
        oxDataSet.setDrawValues(false) //不显示数值
        oxDataSet.setDrawCircles(false) //不显示圆点
        // 设置高亮十字光标线的虚化:设置第二个参数为虚线间隔
        oxDataSet.enableDashedHighlightLine(10f, 0f, 0f)
        // 设置十字光标线的颜色
        oxDataSet.isHighlightEnabled = true //显示高亮
        oxDataSet.highLightColor = highLightColor
        oxDataSet.setDrawHorizontalHighlightIndicator(false) //水平的高亮线不绘制
        //设置原点的颜色
        oxDataSet.circleRadius = 2.0f
        //oxDataSet.setDrawCircles(true);
        oxDataSet.circleHoleRadius = 2.0f
        oxDataSet.setCircleColor(context!!.resources.getColor(R.color.color_ff4900))
        oxDataSet.color = lineColor
        //是否填充
        oxDataSet.setDrawFilled(true)
        oxDataSet.fillDrawable = context!!.resources.getDrawable(R.drawable.gradient_ecg_line)
        return oxDataSet
    }

这里就不做过多介绍了,属性参数的意思都有注释,如果需要改线条的颜色或者粗细,只用修改对应的属性值就好了

5.最后就是动态添加数据环节,代码如下:

 /**
     * 动态增加折线数据
     *
     * @param entries 折线的数据
     * @return void
     * @time 2019-10-16 15:07:53
     */
    fun addEntry(entries: ArrayList<Entry>) {
        if (null == ecgDataSet) {
//            realTimeList.clear()
//            realTimeList.addAll(entries)
            ecgDataSet = buildOXDataSet(entries)
            (lineDataSets as ArrayList).add(ecgDataSet!!)
        } else {
            val lineDataSet = lineData!!.getDataSetByLabel(
                LABEL_ECG,
                true
            ) as LineDataSet
//            realTimeList.addAll(entries)
//            lineDataSet.entries = realTimeList
            //changeLineStatues(lineDataSet);
            for (entry in entries) {
                lineDataSet.addEntry(entry)
            }
        }
        val entry = entries[entries.size - 1]
        //设置上面的limitline动态增加
        val lineDataSet = lineData!!.getDataSetByLabel(LABEL_LIMIT_LINE_UP, true)
        if (lineDataSet.entryCount >= 2 && entry.x > xAxisVisibleValueRange) {
            lineDataSet.removeEntry(lineDataSet.entryCount - 1)
            lineDataSet.addEntry(Entry(entry.x, LIMIT_VALUE_MAX))
        }
        lineData!!.notifyDataChanged()
        lineChart!!.notifyDataSetChanged()
        //控制x轴值的显示范围
        lineChart!!.setVisibleXRangeMaximum(xAxisVisibleValueRange)
        if (entry.x > xAxisVisibleValueRange) {
            lineChart!!.moveViewToX(entry.x) //移动到最后一个
        } else {
            lineChart!!.moveViewToX(0f)
        }
    }

这里主要是通过getDataSetByLabel()函数去获取linechart中已经有的曲线的linedataset,同时把获取的数据添加到对应的linedataset里面,同时将视图拉向最后一个点的x轴最大值,要实现动态的,必须设置x轴的最大视图范围,通过函数名:setVisibleXRangeMaximum()去设置。以上就是动态实现心率的相关代码

6.最后贴出全部的代码:

/**
 * @ClassName EcgChartHelper
 * @Description TODO
 * @Author  Darcy
 * @Date 2021/9/17 16:44
 * @Version 1.0
 */
class EcgChartHelper(chart: LineChart, context: Context) {

    private var xAxis: XAxis? = null
    private var leftAxis: YAxis? = null
    private var rightAxis: YAxis? = null
    private var context: Context? = context
    private var lineChart: LineChart? = chart

    //高亮线的颜色
    private val highLightColor = -0x3e3717

    //网格线宽度
    private val gridLineWidth = 1.0f

    //Y坐标轴刻度文字大小
    private val axisYTextSize = 10f

    //X坐标轴刻度文字大小
    private val axisXTextSize = 8f

    //坐标轴刻度文字颜色
    private val axisTextColor = -0x5c5c5d
    private val Y_MAX = 120f //正常范围边界最大值
    private val Y_MIN = 70f //正常范围边界最小值
    private val yAxisLabelCount = 20 //y轴刻度数

    // x轴显示的值范围大小,
    private val xAxisVisibleValueRange = 300.0f

    private val LABEL_LIMIT_LINE_UP = "limit_line_up"

    //有效值(灰色区域)
    private val LIMIT_VALUE_MIN = 90f //有效范围的最小值

    private val LIMIT_VALUE_MAX = 100f //有效范围的最大值

    //灰色区域最大值
    private val maxRangeVaule = 300.0f

    //灰色区域颜色值
    private val limitAreaColor = -0xdf243a

    private val LABEL_ECG = "label_ecg"

    //X轴的刻度数,
    private val xAxisLabelCount = 60

    //线宽
    private val lineWidth = 1.0f

    //private val lineColor: Int =  -0x7f006800
    private val lineColor: Int = -0x5bd00


    //设置灰色区域(有效的范围值)
    private fun bulidLimitArea() {
        //灰色区域绘制
        val dataSet: LineDataSet = buildUpLimitDataSet()
        (lineDataSets as ArrayList).add(dataSet)
        //添加一个 LineData
        lineData = LineData(lineDataSets)
        lineChart!!.data = lineData
        lineChart!!.invalidate()
    }

    /**
     * 设置限制线.基线(预警线的线条)
     *
     * @return void
     * @time 2020-7-30 18:09:16
     */
    private fun buildUpLimitDataSet(): LineDataSet {
        val limitLineWidth = 0.1f
        val entries: ArrayList<Entry> = ArrayList()
        entries.add(Entry(0f, LIMIT_VALUE_MAX))
        entries.add(Entry(maxRangeVaule, LIMIT_VALUE_MAX))
        val dataSet = LineDataSet(entries, LABEL_LIMIT_LINE_UP)
        dataSet.lineWidth = limitLineWidth
        dataSet.mode = LineDataSet.Mode.LINEAR //
        dataSet.setDrawValues(false) //不显示数值
        dataSet.setDrawCircles(false) //不显示圆点
        dataSet.isHighlightEnabled = false
        dataSet.setDrawFilled(true)
        dataSet.fillFormatter = LimitLineFillFormatter(LIMIT_VALUE_MIN)
        dataSet.fillColor = limitAreaColor
        dataSet.color = -0x111112
        dataSet.fillAlpha = 0x1a

        return dataSet
    }

    /**
     * Y坐标轴设置
     *
     * @return void
     * @time 2021-9-16 16:25:46
     */
    private fun initYAxis() {
        leftAxis?.let {
            //是否绘制轴线
            it.setDrawAxisLine(true)
            //设置轴线的颜色
            it.axisLineColor = context!!.resources.getColor(R.color.color_f3f3f3)
            //是否绘制网格线
            it.setDrawGridLines(true) //横的线(与Y轴有关)
            //y轴的线为虚线
            //leftAxis.enableGridDashedLine(10f, 5f, 0f);
            it.gridLineWidth = gridLineWidth
            //设置网格线的颜色
            it.gridColor = context!!.resources.getColor(R.color.color_f3f3f3)
            it.textSize = axisYTextSize
            it.textColor = axisTextColor
            //leftAxis.setSpaceMin(20);
            //leftAxis.setSpaceMax(20);
            //字体距离曲线的位置
            it.xOffset = 6f
            it.yOffset = 0f
            //设置最大值和最小值
            it.axisMinimum = Y_MIN
            it.axisMaximum = Y_MAX
            //y轴坐标点个数
            it.labelCount = yAxisLabelCount

            it.valueFormatter = StepYaxisValueFormat()
        }
        ///右边的y轴///
        rightAxis?.let {
            it.isEnabled = false
            // it.setDrawAxisLine(false)
            // it.spaceMax = 0f
        }
    }

    /**
     * X坐标轴设置
     *
     * @return void
     * @time 2020-7-30 18:09:24
     */
    private fun initXAxis() {
        xAxis?.let {
            //是否绘制网格线
            it.setDrawGridLines(true) //竖的线(与X轴有关)
            //网格线的宽度
            it.gridLineWidth = gridLineWidth
            //网格颜色
            it.gridColor = context!!.resources.getColor(R.color.color_f3f3f3)
            //字体距离曲线的位置
            it.yOffset = 0f
            it.xOffset = 0f
            it.position = XAxis.XAxisPosition.BOTTOM // 设置X轴的位置
            it.setDrawAxisLine(true) //是否显示X轴
            //轴线的颜色
            it.axisLineColor = context!!.resources.getColor(R.color.color_f3f3f3)
            it.textSize = axisXTextSize
            it.textColor = axisTextColor
            //xAxis.setSpaceMin(5);//小于最小值5开始画
            it.spaceMax = 0f //大于最大值10
            it.axisMinimum = 0f //x轴显示的最小值

            //只有不是实时曲线的时候才设置这个值
            // it.axisMaximum = xAxisVisibleValueRange //x轴显示的最大值

            //xAxis.mAxisRange=2f;
            it.setLabelCount(xAxisLabelCount, false)
            it.valueFormatter = StepXAxisValueFormat()
        }

    }

    /**
     * 图表LineChart设置
     *
     * @return void
     * @time 2020-7-30 18:09:20
     */
    private fun initLineChart() {
        lineChart?.let {
            /*图表设置***/
            it.setTouchEnabled(true) // 设置是否可以触摸
            //是否启用chart绘图区后面的背景矩形将绘制
            it.setDrawGridBackground(false)
            //        //设置网格背景应与绘制的颜色
            it.setGridBackgroundColor(-0x1)
            //设置markView
//        TempMarkView myMarkerView = new TempMarkView(context);
//        myMarkerView.setChartView(lineChart);
//        lineChart.setMarker(myMarkerView);
            //启用/禁用绘制图表边框(chart周围的线)。
            it.setDrawBorders(false)
            //是否可以拖动
            it.isDragEnabled = true
            //启用/禁用缩放图表上的两个轴
            it.setScaleEnabled(false)
            //设置在曲线图中显示的最大数量
//        vMutlilineChart.setVisibleXRangeMaximum(40);//可视范围的值的范围
            it.setNoDataText("")
            val description = Description()
            description.isEnabled = false
            description.text = "" //我是描述信息
            it.description = description
            //是否显示高亮线,十字线条
            it.isHighlightPerTapEnabled = false
            it.isHighlightPerDragEnabled = false
            val legend: Legend = it.legend
            //legend.setWordWrapEnabled(false);//设置标签是否换行(当多条标签时 需要换行显示、如上右图)true:可换行。false:不换行
            legend.isEnabled = false //隐藏图例
        }
    }

    /**
     * 计步的折线图
     *
     * @return void
     * @time 2021-9-16 17:06:17
     */
    private fun buildOXDataSet(entries: List<Entry>): LineDataSet? {
        return buildOxDataSet(entries, LABEL_ECG)
    }

    /**
     * 计步的折线图
     *
     * @return void
     * @time 2021-9-16 17:06:04
     */
    private fun buildOxDataSet(entries: List<Entry>, label: String): LineDataSet {
        //温度曲线设置
        val oxDataSet = LineDataSet(entries, label)
        oxDataSet.lineWidth = lineWidth
        oxDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER //设置为贝塞尔曲线
        oxDataSet.setDrawValues(false) //不显示数值
        oxDataSet.setDrawCircles(false) //不显示圆点
        // 设置高亮十字光标线的虚化:设置第二个参数为虚线间隔
        oxDataSet.enableDashedHighlightLine(10f, 0f, 0f)
        // 设置十字光标线的颜色
        oxDataSet.isHighlightEnabled = true //显示高亮
        oxDataSet.highLightColor = highLightColor
        oxDataSet.setDrawHorizontalHighlightIndicator(false) //水平的高亮线不绘制
        //设置原点的颜色
        oxDataSet.circleRadius = 2.0f
        //oxDataSet.setDrawCircles(true);
        oxDataSet.circleHoleRadius = 2.0f
        oxDataSet.setCircleColor(context!!.resources.getColor(R.color.color_ff4900))
        oxDataSet.color = lineColor
        //是否填充
        oxDataSet.setDrawFilled(true)
        oxDataSet.fillDrawable = context!!.resources.getDrawable(R.drawable.gradient_ecg_line)
        return oxDataSet
    }

    private var ecgDataSet: LineDataSet? = null
    private val lineDataSets: List<LineDataSet> = ArrayList()
    private var lineData: LineData? = null

    /**
     * 添加数据
     *
     * @param entries 折线的数据
     * @return void
     * @time 2021-9-16 17:08:48
     */
    fun addEntries(entries: ArrayList<Entry>) {
        //先清除存在的点
        lineChart!!.clearValues()
        ecgDataSet = buildOXDataSet(entries)
        (lineDataSets as ArrayList).add(ecgDataSet!!)
        //控制网格不变
        if (entries.isNotEmpty() && entries[entries.size - 1].x > xAxisVisibleValueRange) {
            xAxis!!.spaceMax = 0f
        } else {
            val max =
                if (entries.size == 0) xAxisVisibleValueRange else xAxisVisibleValueRange - entries[entries.size - 1].x
            xAxis!!.spaceMax = max
        }
        lineData?.notifyDataChanged()
        lineChart!!.notifyDataSetChanged()
        lineChart!!.setVisibleXRangeMinimum(xAxisVisibleValueRange)
        //lineChart!!.moveViewToX(entries.size.toFloat())
    }

    /**
     * 动态增加折线数据
     *
     * @param xValue x轴对应的值
     * @param yValue y轴对应的值
     * @return void
     * @time 2020-8-24 15:55:08
     */
    fun addEntry(xValue: Float, yValue: Float) {
        addEntry(Entry(xValue, yValue))
    }

    /**
     * 动态增加折线数据
     *
     * @param entry 折线的数据
     * @return void
     * @time 2020-8-24 15:55:11
     */
    fun addEntry(entry: Entry) {
        val entries = java.util.ArrayList<Entry>()
        entries.add(entry)
        addEntry(entries)
    }


    var realTimeList: ArrayList<Entry> = ArrayList()

    /**
     * 动态增加折线数据
     *
     * @param entries 折线的数据
     * @return void
     * @time 2019-10-16 15:07:53
     */
    fun addEntry(entries: ArrayList<Entry>) {
        if (null == ecgDataSet) {
//            realTimeList.clear()
//            realTimeList.addAll(entries)
            ecgDataSet = buildOXDataSet(entries)
            (lineDataSets as ArrayList).add(ecgDataSet!!以上是关于Koltin实现动态心率曲线的主要内容,如果未能解决你的问题,请参考以下文章

毕业设计 基于STM32单片机生理监控心率脉搏TFT彩屏波形曲线设计

stm32视频教程分享:心率检测仪的设计与实现

WPF 实现心电图曲线绘制

华为哪个手环可以测心电图?

基于uFUN开发板的心率计Qt上位机的实现

是否可以动态编译和执行 C# 代码片段?