1
0
mirror of https://github.com/dzeiocom/OpenHealth.git synced 2025-06-07 15:29:55 +00:00

misc: Continue working on Chart

This commit is contained in:
Florian Bouillon 2022-07-25 17:37:02 +02:00
parent 39c7c507c5
commit 196fcf5da0
4 changed files with 78 additions and 19 deletions

View File

@ -41,6 +41,8 @@ class StepsHomeFragment :
viewModel.items.observe(viewLifecycleOwner) { list ->
adapter.set(list)
chart.numberOfEntries = list.size
chart.numberOfLabels = 2
val strings = ArrayList<String>()
val values = ArrayList<Int>()
@ -50,10 +52,14 @@ class StepsHomeFragment :
values.add(it.value)
}
chart.yAxis.max = 10
chart.setBottomTextList(strings)
chart.setDataList(
values
)
chart.refresh()
}
}
}

View File

@ -0,0 +1,6 @@
package com.dzeio.charts
class Axis<T> {
var max: T? = null
var min: T? = null
}

View File

@ -0,0 +1,6 @@
package com.dzeio.charts
data class Entry(
val x: Float,
val y: Double
)

View File

@ -8,7 +8,11 @@ import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
import android.view.View
import com.dzeio.charts.Axis
import com.dzeio.charts.Entry
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
class BarChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
View(context, attrs) {
@ -20,23 +24,21 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
/**
* Nunber of entries displayed at the same time
*/
val numberOfEntries = 5
var numberOfEntries = 5
/**
* Number of labels displayed at the same time
*/
val numberOfLabels = 3
var numberOfLabels = 3
/**
* Spacing between entries
*/
val spacing = 22
var spacing = 22
/**
* top margin from the canvas
*/
@Deprecated("Not needed anymore, Use the parent Padding/Margin")
private val topMargin: Int = 5
val xAxis: Axis<Int> = Axis()
val yAxis: Axis<Int> = Axis()
private val textTopMargin = 5
@ -84,13 +86,25 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
}
}
fun setList(list: ArrayList<Entry>) {
}
fun refresh(animate: Boolean = true) {
if (animate) {
removeCallbacks(animator)
post(animator)
} else {
postInvalidate()
}
}
/**
* dataList will be reset when called is method.
*
* @param bottomStringList The String ArrayList in the bottom.
*/
fun setBottomTextList(bottomStringList: ArrayList<String>?) {
barWidth = measuredWidth / numberOfEntries - spacing
bottomTextList = bottomStringList
val r = Rect()
bottomTextDescent = 0
@ -99,7 +113,7 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
if (bottomTextHeight < r.height()) {
bottomTextHeight = r.height()
}
Log.d(TAG, measuredWidth.toString())
// Log.d(TAG, measuredWidth.toString())
// if (autoSetWidth && barWidth < r.width()) {
// barWidth = r.width()
// }
@ -107,7 +121,6 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
bottomTextDescent = abs(r.bottom)
}
}
postInvalidate()
}
/**
@ -116,7 +129,7 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
fun setDataList(list: ArrayList<Int>) {
barWidth = measuredWidth / numberOfEntries - spacing
// Calculate max
val max = list.reduce { acc, i -> if (acc > i) return@reduce acc else return@reduce i }
val max = yAxis.max ?: list.reduce { acc, i -> return@reduce if (acc > i) acc else i }
targetPercentList = ArrayList()
for (integer in list) {
@ -135,35 +148,63 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
percentList.removeAt(percentList.size - 1)
}
}
removeCallbacks(animator)
post(animator)
}
override fun onDraw(canvas: Canvas) {
if (percentList.isNotEmpty()) {
for (i in 1 until percentList.size) {
val left = spacing * i + barWidth * (i - 1)
Log.d(TAG, "$spacing, $i, $barWidth = $left")
// Log.d(TAG, "$spacing, $i, $barWidth = $left")
val right = (spacing + barWidth) * i
val bottom = height - bottomTextHeight - textTopMargin
val top = topMargin + ((bottom - topMargin) * percentList[i - 1])
val top = bottom * percentList[i - 1]
rect.set(left, top.toInt(), right, bottom)
canvas.drawRect(rect, fgPaint)
}
}
if (bottomTextList != null && !bottomTextList!!.isEmpty()) {
if (bottomTextList != null && bottomTextList!!.isNotEmpty() && numberOfLabels > 0) {
val rect = Rect()
val size = bottomTextList!!.size
var i = 1
var items = size / max(2, (numberOfLabels - 2))
// handle cases where size is even and numberOfLabels is 3
if (size % 2 != 0) {
items += 1
}
Log.i(TAG, "$size / max($numberOfLabels - 2, 2) = $items")
for (s in bottomTextList!!) {
if ((numberOfLabels <= 2 || i % items != 0) && i != 1 && i != size) {
i++
continue
}
Log.i(TAG, "Drawing $i")
textPaint.getTextBounds(s, 0, s.length, rect)
canvas.drawText(
s,
(spacing * i + barWidth * (i - 1) + barWidth / 2).toFloat(),
// handle last entry overflowing
min(
// handle first entry overflowing
max(
(spacing * i + barWidth * (i - 1) + barWidth / 2).toFloat(),
rect.width() / 2f
),
measuredWidth - rect.width() / 2f
),
(height - bottomTextDescent).toFloat(),
textPaint
)
i++
if (numberOfLabels == 1) {
break
}
}
}
}