1
0
mirror of https://github.com/dzeiocom/OpenHealth.git synced 2025-06-07 07:19:54 +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 -> viewModel.items.observe(viewLifecycleOwner) { list ->
adapter.set(list) adapter.set(list)
chart.numberOfEntries = list.size
chart.numberOfLabels = 2
val strings = ArrayList<String>() val strings = ArrayList<String>()
val values = ArrayList<Int>() val values = ArrayList<Int>()
@ -50,10 +52,14 @@ class StepsHomeFragment :
values.add(it.value) values.add(it.value)
} }
chart.yAxis.max = 10
chart.setBottomTextList(strings) chart.setBottomTextList(strings)
chart.setDataList( chart.setDataList(
values 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.AttributeSet
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import com.dzeio.charts.Axis
import com.dzeio.charts.Entry
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
class BarChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) : class BarChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
View(context, attrs) { View(context, attrs) {
@ -20,23 +24,21 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
/** /**
* Nunber of entries displayed at the same time * Nunber of entries displayed at the same time
*/ */
val numberOfEntries = 5 var numberOfEntries = 5
/** /**
* Number of labels displayed at the same time * Number of labels displayed at the same time
*/ */
val numberOfLabels = 3 var numberOfLabels = 3
/** /**
* Spacing between entries * Spacing between entries
*/ */
val spacing = 22 var spacing = 22
/** val xAxis: Axis<Int> = Axis()
* top margin from the canvas
*/ val yAxis: Axis<Int> = Axis()
@Deprecated("Not needed anymore, Use the parent Padding/Margin")
private val topMargin: Int = 5
private val textTopMargin = 5 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. * dataList will be reset when called is method.
* *
* @param bottomStringList The String ArrayList in the bottom. * @param bottomStringList The String ArrayList in the bottom.
*/ */
fun setBottomTextList(bottomStringList: ArrayList<String>?) { fun setBottomTextList(bottomStringList: ArrayList<String>?) {
barWidth = measuredWidth / numberOfEntries - spacing
bottomTextList = bottomStringList bottomTextList = bottomStringList
val r = Rect() val r = Rect()
bottomTextDescent = 0 bottomTextDescent = 0
@ -99,7 +113,7 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
if (bottomTextHeight < r.height()) { if (bottomTextHeight < r.height()) {
bottomTextHeight = r.height() bottomTextHeight = r.height()
} }
Log.d(TAG, measuredWidth.toString()) // Log.d(TAG, measuredWidth.toString())
// if (autoSetWidth && barWidth < r.width()) { // if (autoSetWidth && barWidth < r.width()) {
// barWidth = r.width() // barWidth = r.width()
// } // }
@ -107,7 +121,6 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
bottomTextDescent = abs(r.bottom) bottomTextDescent = abs(r.bottom)
} }
} }
postInvalidate()
} }
/** /**
@ -116,7 +129,7 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
fun setDataList(list: ArrayList<Int>) { fun setDataList(list: ArrayList<Int>) {
barWidth = measuredWidth / numberOfEntries - spacing barWidth = measuredWidth / numberOfEntries - spacing
// Calculate max // 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() targetPercentList = ArrayList()
for (integer in list) { for (integer in list) {
@ -135,35 +148,63 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
percentList.removeAt(percentList.size - 1) percentList.removeAt(percentList.size - 1)
} }
} }
removeCallbacks(animator)
post(animator)
} }
override fun onDraw(canvas: Canvas) { override fun onDraw(canvas: Canvas) {
if (percentList.isNotEmpty()) { if (percentList.isNotEmpty()) {
for (i in 1 until percentList.size) { for (i in 1 until percentList.size) {
val left = spacing * i + barWidth * (i - 1) 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 right = (spacing + barWidth) * i
val bottom = height - bottomTextHeight - textTopMargin 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) rect.set(left, top.toInt(), right, bottom)
canvas.drawRect(rect, fgPaint) 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 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!!) { 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( canvas.drawText(
s, 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(), (height - bottomTextDescent).toFloat(),
textPaint textPaint
) )
i++ i++
if (numberOfLabels == 1) {
break
}
} }
} }
} }