feat: Make sample more customizable (#43)

This commit is contained in:
2023-02-16 10:07:41 +01:00
committed by GitHub
parent 1a812acb9e
commit 3df7541505
24 changed files with 798 additions and 531 deletions

View File

@ -22,7 +22,7 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet
View(context, attrs), ChartViewInterface {
private companion object {
const val TAG = "Charts/ChartView"
const val TAG = "ChartView"
}
override val animator: Animation = Animation()
@ -97,6 +97,10 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet
refresh()
}
setOnToggleScroll {
// note: true == no scroll
parent?.requestDisallowInterceptTouchEvent(!it && (yAxis.scrollEnabled || xAxis.scrollEnabled))
}
setOnChartClick { x, y ->
if (getDataset().isEmpty()) {
return@setOnChartClick
@ -161,15 +165,11 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet
// invalidate the view
invalidate()
// removeCallbacks(animator)
// post(animator)
}
private var lastRun = runUpdates
override fun onDraw(canvas: Canvas) {
// don't draw anything if everything is empty
if (!runUpdates && lastRun == runUpdates && series.isEmpty() || series.maxOf { it.entries.size } == 0) {
if (!runUpdates || series.isEmpty() || series.maxOf { it.entries.size } == 0) {
super.onDraw(canvas)
return
}

View File

@ -92,18 +92,14 @@ class XAxis(
var maxHeight = 0f
val graphIncrement = space.width() / (labelCount - 1)
val valueIncrement = getDataWidth() / (labelCount - 1)
val valueIncrement = getDataWidth() / (labelCount - 1).coerceAtLeast(1)
for (index in 0 until labelCount) {
val text = onValueFormat(x + valueIncrement * index)
textPaint.getTextBounds(text, 0, text.length, rect)
getPositionOnRect(valueIncrement, space)
maxHeight = maxHeight.coerceAtLeast(rect.height().toFloat() + 1)
var xPos = space.left + graphIncrement * index
if (xPos + rect.width() > space.right) {
xPos = space.right - rect.width()
}
val xPos = getPositionOnRect(x + valueIncrement * index, space).toFloat()
canvas.drawText(
text,
@ -134,8 +130,8 @@ class XAxis(
.coerceIn(1.0, drawableSpace.width().toDouble())
// handle grouped series
if (view.type == ChartType.GROUPED) {
return result / view.series.size - spacing / 2 * (view.series.size - 1)
if (view.type == ChartType.GROUPED && view.series.size > 1) {
return ((result - (spacing / 2 * view.series.size)) / view.series.size).coerceAtLeast(1.0)
}
return result
@ -145,5 +141,4 @@ class XAxis(
// TODO: handle the auto dataWidth better (still not sure it is good enough)
return dataWidth ?: (getXMax() - getXMin() + 1)
}
}

View File

@ -162,7 +162,7 @@ class YAxis(
val max = getYMax() - min
var maxWidth = 0f
val valueIncrement = max / (labelCount - 1)
val valueIncrement = max / (labelCount - 1).coerceAtLeast(1)
for (index in 0 until labelCount) {
val value = min + (valueIncrement * index)

View File

@ -73,6 +73,11 @@ class Annotation(
val xCenter = view.xAxis.getEntryWidth(space) / 2.0 + x
if (xCenter < space.left || xCenter > space.right) {
entry = null
return
}
val xText = annotationSubTitleFormat.invoke(entry!!)
val yText = annotationTitleFormat.invoke(entry!!)

View File

@ -1,160 +0,0 @@
package com.dzeio.charts.series
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.RectF
import android.util.Log
import kotlin.math.max
class BarSerie : SerieAbstract() {
companion object {
const val TAG = "DzeioCharts/BarSerie"
}
var spacing: Float = 8f
/**
* Values displayed on the grapd
*/
var displayedDatas = arrayListOf<Float>()
/**
* Target values
*/
var targetDatas = arrayListOf<Float>()
var targetPercentList = arrayListOf<Float>()
var percentList = arrayListOf<Float>()
var previousRefresh = 0
private var fgPaint: Paint = Paint().apply {
isAntiAlias = true
}
private val r = Rect()
override fun onUpdate(): Boolean {
var needNewFrame = false
for (i in targetPercentList.indices) {
val value = view.animation.updateValue(
1f,
targetPercentList[i],
percentList[i],
0f,
0.00f
)
if (value != percentList[i]) {
needNewFrame = true
percentList[i] = value
}
}
return needNewFrame
}
override fun prepareData() {
val max: Float = if (view.yAxis.max != null) view.yAxis.max!! else {
getYMax(true)
}
targetPercentList = arrayListOf()
// Log.d(TAG, "offset: ${view.getXOffset()}, displayed: ${view.getDisplayedEntries()}")
for (item in getDisplayedEntries()) {
// // // Process bottom texts
// val text = view.xAxis.onValueFormat(item.x)
// bottomTexts.add(text)
//
// // get Text boundaries
// view.xAxis.labels.build().getTextBounds(text, 0, text.length, r)
//
// // get height of text
// if (bottomTextHeight < r.height()) {
// bottomTextHeight = r.height()
// }
//
// // get text descent
// val descent = abs(r.bottom)
// if (bottomTextDescent < descent) {
// bottomTextDescent = descent
// }
// process values
// Log.d(TAG, item.y.toString())
// add to animations the values
targetPercentList.add(1 - item.y / max)
}
// post list
val offset = view.getXOffset()
val movement = offset - previousRefresh
Log.d(TAG, "$offset - $previousRefresh = $movement")
if (movement != 0) {
previousRefresh = offset
}
// if (movement != 0) {
// Log.d(TAG, movement.toString())
// }
if (movement >= 1) {
percentList = percentList.subList(1, percentList.size).toCollection(ArrayList())
percentList.add(1f)
} else if (movement <= -1) {
percentList = percentList.subList(0, percentList.size - 1).toCollection(ArrayList())
percentList.add(0, 1f)
}
if (percentList.isEmpty() || percentList.size < targetPercentList.size) {
val temp = targetPercentList.size - percentList.size
for (i in 0 until temp) {
percentList.add(1f)
}
} else if (percentList.size > targetPercentList.size) {
val temp = percentList.size - targetPercentList.size
for (i in 0 until temp) {
percentList.removeAt(percentList.size - 1)
}
}
fgPaint.color = view.yAxis.color
}
override fun displayData(canvas: Canvas, rect: RectF) {
val barWidth = (rect.width() - view.padding * 2) / view.getDisplayedEntries() - spacing
if (percentList.isNotEmpty()) {
// draw each rectangles
for (i in 1..percentList.size) {
// Log.d(TAG, percentList[i - 1].toString())
val left = rect.left + spacing * i + barWidth * (i - 1).toFloat() + view.padding
// Log.d(TAG, "$spacing, $i, $barWidth = $left")
val right = rect.left + (spacing + barWidth) * i.toFloat()
val bottom = rect.top + rect.height() - view.padding
val top = (bottom - rect.top) * percentList[i - 1] + view.padding
// create rounded rect
canvas.drawRoundRect(left, top, right, bottom, 8f, 8f, fgPaint)
// remove the bottom corners DUH
canvas.drawRect(left, max(top, bottom - 8f), right, bottom, fgPaint)
val targetTop = (bottom - rect.top) * targetPercentList[i - 1]
val text = view.yAxis.onValueFormat(getYMax(true) - getYMax(true) * targetPercentList[i - 1], true)
view.xAxis.labels.build().getTextBounds(text, 0, text.length, r)
val doDisplayIn =
r.width() + 10f < barWidth && bottom - targetTop > r.height() + 40f
if (view.debug || !doDisplayIn || (doDisplayIn && bottom - top > r.height() + 40f)) {
val y = if (doDisplayIn) top + r.height() + 20f else top - r.height()
canvas.drawText(
text,
left + (right - left) / 2,
y,
view.xAxis.labels.build()
)
}
}
}
}
}