desc:气体浓度折线图

main
xiaowusky 2 years ago
parent 1a4bebe265
commit a1a032391e

@ -67,4 +67,6 @@ dependencies {
implementation 'com.google.android.material:material:1.5.0'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.0.0'
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
}

@ -114,6 +114,14 @@
android:screenOrientation="landscape"
android:exported="false"
android:theme="@style/FullscreenTheme" />
<activity
android:name=".watcher.ui.ChartActivity"
android:exported="true"
android:screenOrientation="landscape" />
<activity
android:name=".watcher.ui.GasListActivity"
android:exported="true"
android:screenOrientation="landscape" />
</application>
</manifest>

@ -0,0 +1,161 @@
package com.yinuo.safetywatcher.watcher.ui
import android.graphics.Color
import android.view.KeyEvent
import android.view.View
import com.common.commonlib.db.entity.Gas
import com.github.mikephil.charting.components.XAxis
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter
import com.yinuo.safetywatcher.R
import com.yinuo.safetywatcher.databinding.ActivityChartBinding
import com.yinuo.safetywatcher.watcher.base.NoOptionsActivity
import com.yinuo.safetywatcher.watcher.utils.ChartBridge
import java.text.SimpleDateFormat
import java.util.Locale
class ChartActivity : NoOptionsActivity() {
private val mBinding: ActivityChartBinding by lazy {
ActivityChartBinding.inflate(layoutInflater)
}
override fun getTopBarTitle(): String {
return getString(R.string.chart)
}
override fun generateContentView(): View {
return mBinding.root
}
private val dataFormat = SimpleDateFormat("MM/dd HH:mm:ss", Locale.ROOT)
var mSelectGas: String? = ""
var mGases: List<Gas>? = null
private var mXPositionIndex = 0
var mXScale = 5f
private val pointCountPerPage = 8
override fun initView() {
initData()
setKeyControl()
setChartView()
setXAxis()
setData()
}
private fun initData() {
mSelectGas = ChartBridge.getSelectGas()
val mapData = ChartBridge.getMapData()
mGases = mapData?.get(mSelectGas)
}
private fun setKeyControl() {
mBinding.container.setOnKeyListener { v, keyCode, event ->
if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT && event.action == KeyEvent.ACTION_DOWN) {
// 获取图标Matrix参数
if (mXPositionIndex < mXScale - 1) {
mXPositionIndex++
// 获取图标Matrix参数
val mMatrix = mBinding.chart.viewPortHandler.matrixTouch
// 设置平移距离(这里是平移到图标的最右边)
val distance: Float = mBinding.chart.contentRect.width() * (mXPositionIndex)
mMatrix.setTranslate(-distance, 0f)
//两个参数分别是x,y轴的缩放比例。
mMatrix.preScale(mXScale, 1f)
// 刷新
mBinding.chart.viewPortHandler.refresh(mMatrix, mBinding.chart, true)
return@setOnKeyListener true
}
} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT && event.action == KeyEvent.ACTION_DOWN) {
// 获取图标Matrix参数
if (mXPositionIndex > 0) {
mXPositionIndex--
// 获取图标Matrix参数
val mMatrix = mBinding.chart.viewPortHandler.matrixTouch
// 设置平移距离(这里是平移到图标的最右边)
val distance: Float = mBinding.chart.contentRect.width() * (mXPositionIndex)
mMatrix.setTranslate(-distance, 0f)
//两个参数分别是x,y轴的缩放比例。
mMatrix.preScale(mXScale, 1f)
// 刷新
mBinding.chart.viewPortHandler.refresh(mMatrix, mBinding.chart, true)
return@setOnKeyListener true
}
}
return@setOnKeyListener false
}
}
private fun setChartView() {
mBinding.chart.apply {
// disable description text
description.isEnabled = false
// enable touch gestures
setTouchEnabled(true)
setDrawGridBackground(false)
isScaleYEnabled = false
legend.isEnabled = false
}
}
private fun setXAxis() {
mBinding.chart.apply {
xAxis.apply {
position = XAxis.XAxisPosition.BOTTOM
textColor = Color.WHITE
textSize = 16f
setLabelCount((pointCountPerPage + 1).toInt(), true)
setVisibleXRangeMaximum(pointCountPerPage.toFloat())
granularity = 1f; // 设置X轴坐标之间的最小间隔
valueFormatter = object : IndexAxisValueFormatter() {
override fun getFormattedValue(value: Float): String {
if (value < (mGases?.size ?: 0)) {
val baseTime = mGases?.get(value.toInt())?.time
return dataFormat.format(baseTime)
}
return ""
}
}
}
axisRight.isEnabled = false
axisLeft.textColor = Color.WHITE
axisLeft.textSize = 20f
}
}
private fun setData() {
mBinding.chart.apply {
//设置数据
val entries = arrayListOf<Entry>()
mGases?.forEachIndexed { index, gas ->
entries.add(Entry(index.toFloat(), gas.gasValue.toFloat()))
}
//一个LineDataSet就是一条线
val lineDataSet = LineDataSet(entries, mSelectGas);
lineDataSet.valueTextColor = Color.WHITE
lineDataSet.valueTextSize = 20f
lineDataSet.color = Color.GREEN
val index = entries.size - 1
val scale = if (index % pointCountPerPage == 0) (
index / pointCountPerPage
) else (
(index + pointCountPerPage) / pointCountPerPage
)
mBinding.chart.xAxis.axisMaximum = (scale * pointCountPerPage).toFloat()
mXScale = scale.toFloat()
val data = LineData(lineDataSet);
setData(data)
val mMatrix = mBinding.chart.viewPortHandler.matrixTouch
mMatrix.postScale(mXScale, 1f);//两个参数分别是x,y轴的缩放比例。例如将x轴的数据放大为之前的1.5倍
mBinding.chart.viewPortHandler.refresh(mMatrix, this, false)
}
}
}

@ -0,0 +1,44 @@
package com.yinuo.safetywatcher.watcher.ui
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import com.yinuo.safetywatcher.R
import com.yinuo.safetywatcher.databinding.ActivitySensorBinding
import com.yinuo.safetywatcher.watcher.base.NoOptionsActivity
import com.yinuo.safetywatcher.watcher.ui.adapter.GasListAdapter
import com.yinuo.safetywatcher.watcher.utils.ChartBridge
class GasListActivity : NoOptionsActivity() {
private val mBingding by lazy {
ActivitySensorBinding.inflate(layoutInflater)
}
private val mAdapter by lazy {
GasListAdapter()
}
override fun getTopBarTitle(): String? {
return getString(R.string.gas_list)
}
override fun generateContentView(): View {
return mBingding.root
}
override fun initView() {
mBingding.rvSensor.layoutManager = LinearLayoutManager(this@GasListActivity)
mBingding.rvSensor.adapter = mAdapter
queryData()
}
private fun queryData() {
val mapData = ChartBridge.getMapData()
val list = arrayListOf<String>()
mapData?.forEach { (t, u) ->
list.add(t)
}
mAdapter.setData(list)
}
}

@ -1,6 +1,7 @@
package com.yinuo.safetywatcher.watcher.ui
import android.annotation.SuppressLint
import android.content.Intent
import android.view.View
import androidx.activity.result.contract.ActivityResultContracts
import androidx.lifecycle.lifecycleScope
@ -15,6 +16,7 @@ import com.yinuo.safetywatcher.watcher.constant.DEFAULT_QUERY_TIME_INTERVAL
import com.yinuo.safetywatcher.watcher.constant.TimeStep
import com.yinuo.safetywatcher.watcher.ui.adapter.HistoryDataAdapter
import com.yinuo.safetywatcher.watcher.ui.view.CommonTopBar
import com.yinuo.safetywatcher.watcher.utils.ChartBridge
import com.yinuo.safetywatcher.watcher.utils.DateUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -25,11 +27,22 @@ class QueryDataActivity : BaseActivity() {
ActivityQueryDataBinding.inflate(layoutInflater)
}
private var mGasNewMap: HashMap<String, MutableList<Gas>>? = null
override fun onOptionClick(type: Int, target: View) {
if (0 == type) {
queryData()
} else if (1 == type) {
doExportData()
} else if (2 == type) {
goToChartPage()
}
}
private fun goToChartPage() {
mGasNewMap?.let {
ChartBridge.setMapData(it)
startActivity(Intent(this@QueryDataActivity, GasListActivity::class.java))
}
}
@ -37,6 +50,7 @@ class QueryDataActivity : BaseActivity() {
val ops = mutableListOf<CommonTopBar.Option>()
ops.add(CommonTopBar.Option(0, getString(R.string.search)))
ops.add(CommonTopBar.Option(1, getString(R.string.export)))
ops.add(CommonTopBar.Option(2, getString(R.string.chart)))
return ops
}
@ -184,11 +198,12 @@ class QueryDataActivity : BaseActivity() {
}
}
}
val newList = mutableListOf<Gas>()
mGasNewMap = gasNewMap
var newList = mutableListOf<Gas>()
gasNewMap.forEach { (t, u) ->
newList.addAll(u)
}
newList = newList.filter { it.gasValue >= 0.0 } as MutableList<Gas>
newList.sortWith { o1, o2 ->
(o2.time - o1.time).toInt()
}

@ -0,0 +1,37 @@
package com.yinuo.safetywatcher.watcher.ui.adapter
import android.content.Intent
import android.view.LayoutInflater
import android.view.ViewGroup
import com.yinuo.safetywatcher.databinding.LayoutItemGasBinding
import com.yinuo.safetywatcher.watcher.base.BaseRvAdapter
import com.yinuo.safetywatcher.watcher.ui.ChartActivity
import com.yinuo.safetywatcher.watcher.ui.SensorSettingActivity
import com.yinuo.safetywatcher.watcher.utils.ChartBridge
class GasListAdapter :
BaseRvAdapter<String, LayoutItemGasBinding, GasListAdapter.SensorViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SensorViewHolder {
return SensorViewHolder(
LayoutItemGasBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
);
}
class SensorViewHolder(private val binding: LayoutItemGasBinding) :
BaseViewHolder<String, LayoutItemGasBinding>(binding) {
override fun bindView(data: String) {
val context = binding.root.context
binding.root.setOnClickListener {
ChartBridge.setSelectGas(data)
context.startActivity(Intent(context, ChartActivity::class.java))
}
binding.gasName.text = data
}
}
}

@ -0,0 +1,26 @@
package com.yinuo.safetywatcher.watcher.utils
import com.common.commonlib.db.entity.Gas
import java.util.HashMap
object ChartBridge {
private var mGasNewMap: HashMap<String, MutableList<Gas>>? = null
private var mSelectGas:String? = null
fun setMapData(it: HashMap<String, MutableList<Gas>>) {
mGasNewMap = it
}
fun getMapData(): HashMap<String, MutableList<Gas>>? {
return mGasNewMap
}
fun setSelectGas(data: String) {
mSelectGas = data
}
fun getSelectGas(): String? {
return mSelectGas
}
}

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:gravity="center"
android:orientation="vertical">
<RadioGroup
android:id="@+id/rb"
android:layout_width="match_parent"
android:layout_height="wrap_content"></RadioGroup>
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/chart"
android:layout_marginHorizontal="@dimen/_40dp"
android:layout_marginBottom="@dimen/_40dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/_108dp"
android:gravity="center_vertical"
android:focusable="true"
android:orientation="horizontal">
<TextView
android:id="@+id/gas_name"
android:layout_width="@dimen/_300dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/_172dp"
android:text="传感器"
android:textColor="@color/white"
android:textSize="@dimen/_30dp" />
</LinearLayout>

@ -26,6 +26,8 @@
<string name="search">搜索</string>
<string name="export">导出</string>
<string name="chart">折线图</string>
<string name="gas_list">气体列表</string>
<string name="status_ok">正常</string>
<string name="status_offline">离线</string>

@ -3,6 +3,7 @@ buildscript {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'

Loading…
Cancel
Save