MPAndroidChartを使ったリアルタイム更新グラフのサンプルを作成した。
公式にサンプル(https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java)
にあるが、Javaで書かれているため、ここでは公式を参考にKotlinで書いていく。
まず、build.gradleにviewBindingの設定とMPAndroidChartのインポート設定を行う。
app/build.gradle
...
android {
...
buildFeatures {
viewBinding = true
}
}
dependencies {
...
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
}
...
また、レイアウトは以下のように作成する。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/lineChartExample"
android:layout_width="333dp"
android:layout_height="488dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/monitor_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="feedMultiple"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lineChartExample" />
</androidx.constraintlayout.widget.ConstraintLayout>
そこで、MainActivity.ktを以下のように記述。
MainActivity.kt
class MainActivity : AppCompatActivity() {
private var chart: LineChart? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
chart = binding.lineChartExample.apply {
isDragEnabled = false
setTouchEnabled(false)
setScaleEnabled(true)
setDrawGridBackground(false)
setPinchZoom(false)
// setBackgroundColor(Color.LTGRAY)
data = LineData().apply {
// setValueTextColor(Color.WHITE)
addDataSet(createSet("x", Color.RED))
addDataSet(createSet("y", Color.GREEN))
addDataSet(createSet("z", Color.BLUE))
}
description.apply {
isEnabled = false
}
legend.apply {
// textColor = Color.WHITE
form = LegendForm.LINE
}
xAxis.apply {
// textColor = Color.WHITE
// isEnabled = false
setAvoidFirstLastClipping(true)
setDrawGridLines(true)
}
axisLeft.apply {
// textColor = Color.WHITE
axisMaximum = 35.0f
axisMinimum = -5.0f
setDrawGridLines(true)
}
axisRight.apply {
isEnabled = false
}
}
}
private fun addEntry() {
chart?.apply{
data.apply {
val set1 = getDataSetByIndex(0)
val set2 = getDataSetByIndex(1)
val set3 = getDataSetByIndex(2)
addEntry(Entry(set1.entryCount.toFloat(), (Math.random() * 10).toFloat() + 0f), 0)
addEntry(Entry(set2.entryCount.toFloat(), (Math.random() * 10).toFloat() + 10f), 1)
addEntry(Entry(set3.entryCount.toFloat(), (Math.random() * 10).toFloat() + 20f), 2)
notifyDataChanged()
}
notifyDataSetChanged()
setVisibleXRangeMaximum(200.0f)
moveViewToX(data.entryCount.toFloat())
}
}
private fun createSet(label: String, c: Int): LineDataSet {
return LineDataSet(null, label).apply {
axisDependency = AxisDependency.LEFT
color = c
lineWidth = 1.0f
setDrawCircles(false)
setDrawValues(false)
}
}
private var thread: Thread? = null
fun feedMultiple(view: View) {
if (thread != null) thread!!.interrupt()
val runnable = Runnable {
addEntry()
}
thread = Thread(Runnable {
for (i in 0..999) {
runOnUiThread(runnable)
try {
Thread.sleep(25)
} catch (e: InterruptedException) {
e.printStackTrace()
}
}
})
thread!!.start()
}
override fun onPause() {
super.onPause()
if (thread != null) {
thread!!.interrupt()
}
}
}