用MPAndroid 實作動態的心率曲線
廢話不多說,先上圖
上面是實作效果,由于是第一次上傳圖片,不會發動圖,目前就兩張圖片,
- 首先是集成mpchart Android,具體集成方式請直接百度就好
- 先實作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!!)
} 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)
}
}
fun clearData() {
if (lineChart!!.data != null) lineChart!!.clearValues()
//置空保存的橫坐標資料
//setRealXvalue(null)
initLineChart()
initYAxis()
bulidLimitArea()
//initLineDatas()
initXAxis()
lineData!!.notifyDataChanged()
lineChart!!.notifyDataSetChanged()
}
init {
xAxis = chart.xAxis
leftAxis = chart.axisLeft
rightAxis = chart.axisRight
initLineChart()
initXAxis()
initYAxis()
bulidLimitArea()
}
}
以上是動態實作心率曲線的全部代碼,由于是公司的專案,在這里就不放原始碼了,有了這個helper類,直接引入呼叫就好了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/336270.html
標籤:其他
