mirror of
https://github.com/dzeiocom/charts.git
synced 2025-07-23 13:29:54 +00:00
feat: Make sample more customizable (#43)
This commit is contained in:
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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!!)
|
||||
|
||||
|
@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user