mirror of
https://github.com/dzeiocom/OpenHealth.git
synced 2025-04-23 03:12:14 +00:00
feat(charts): Add back the XAxis/YAxis/Scrolling
This commit is contained in:
parent
07d150968e
commit
39f6e7cbef
@ -13,6 +13,9 @@ import com.dzeio.openhealth.core.BaseFragment
|
|||||||
import com.dzeio.openhealth.databinding.FragmentStepsHomeBinding
|
import com.dzeio.openhealth.databinding.FragmentStepsHomeBinding
|
||||||
import com.google.android.material.color.MaterialColors
|
import com.google.android.material.color.MaterialColors
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import java.text.DateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class StepsHomeFragment :
|
class StepsHomeFragment :
|
||||||
@ -61,10 +64,10 @@ class StepsHomeFragment :
|
|||||||
|
|
||||||
chart.apply {
|
chart.apply {
|
||||||
series = arrayListOf(serie)
|
series = arrayListOf(serie)
|
||||||
debug = true
|
// debug = true
|
||||||
|
|
||||||
yAxis.apply {
|
yAxis.apply {
|
||||||
setYMin(0f)
|
setYMax(500f)
|
||||||
textLabel.color = MaterialColors.getColor(
|
textLabel.color = MaterialColors.getColor(
|
||||||
requireView(),
|
requireView(),
|
||||||
com.google.android.material.R.attr.colorOnPrimaryContainer
|
com.google.android.material.R.attr.colorOnPrimaryContainer
|
||||||
@ -79,27 +82,34 @@ class StepsHomeFragment :
|
|||||||
|
|
||||||
xAxis.apply {
|
xAxis.apply {
|
||||||
increment = 3600000.0
|
increment = 3600000.0
|
||||||
displayCount = 168
|
// displayCount = 168
|
||||||
// displayCount = 24
|
displayCount = 10
|
||||||
|
textPaint.color = MaterialColors.getColor(
|
||||||
|
requireView(),
|
||||||
|
com.google.android.material.R.attr.colorOnPrimaryContainer
|
||||||
|
)
|
||||||
|
textPaint.textSize = 32f
|
||||||
|
onValueFormat = onValueFormat@{
|
||||||
|
val formatter = DateFormat.getDateTimeInstance(
|
||||||
|
DateFormat.SHORT,
|
||||||
|
DateFormat.SHORT,
|
||||||
|
Locale.getDefault()
|
||||||
|
)
|
||||||
|
return@onValueFormat formatter.format(Date(it.toLong()))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.items.observe(viewLifecycleOwner) { list ->
|
viewModel.items.observe(viewLifecycleOwner) { list ->
|
||||||
adapter.set(list)
|
adapter.set(list)
|
||||||
|
|
||||||
chart.debug = true
|
|
||||||
|
|
||||||
// chart.animation.enabled = false
|
// chart.animation.enabled = false
|
||||||
// chart.animation.refreshRate = 60
|
// chart.animation.refreshRate = 60
|
||||||
// chart.animation.duration = 300
|
// chart.animation.duration = 300
|
||||||
|
|
||||||
// chart.scroller.zoomEnabled = false
|
// chart.scroller.zoomEnabled = false
|
||||||
|
|
||||||
// chart.xAxis.labels.color = MaterialColors.getColor(
|
|
||||||
// requireView(),
|
|
||||||
// com.google.android.material.R.attr.colorOnBackground
|
|
||||||
// )
|
|
||||||
|
|
||||||
// chart.xAxis.labels.size = 32f
|
// chart.xAxis.labels.size = 32f
|
||||||
|
|
||||||
serie.entries = list.reversed().map {
|
serie.entries = list.reversed().map {
|
||||||
@ -108,32 +118,8 @@ class StepsHomeFragment :
|
|||||||
|
|
||||||
chart.xAxis.x = serie.entries.first().x
|
chart.xAxis.x = serie.entries.first().x
|
||||||
|
|
||||||
// chart.xAxis.onValueFormat = onValueFormat@{
|
|
||||||
// val formatter = DateFormat.getDateTimeInstance(
|
|
||||||
// DateFormat.SHORT,
|
|
||||||
// DateFormat.SHORT,
|
|
||||||
// Locale.getDefault()
|
|
||||||
// )
|
|
||||||
// return@onValueFormat formatter.format(Date(it.toLong()))
|
|
||||||
// }
|
|
||||||
|
|
||||||
chart.refresh()
|
chart.refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
// val scrollView = requireActivity().findViewById<NestedScrollView>(R.id.scrollView)
|
|
||||||
// var scrollEnabled = false
|
|
||||||
// scrollView.setOnTouchListener { view, _ ->
|
|
||||||
// view.performClick()
|
|
||||||
// if (scrollEnabled) {
|
|
||||||
// } else {
|
|
||||||
// return@setOnTouchListener !scrollEnabled
|
|
||||||
// }
|
|
||||||
// return@setOnTouchListener true
|
|
||||||
// }
|
|
||||||
|
|
||||||
// binding.chart.setOnToggleScroll {
|
|
||||||
// Log.d(TAG, it.toString())
|
|
||||||
// scrollEnabled = it
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package com.dzeio.charts
|
package com.dzeio.charts
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.graphics.RectF
|
import android.graphics.RectF
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import com.dzeio.charts.axis.XAxis
|
import com.dzeio.charts.axis.XAxis
|
||||||
@ -21,14 +21,6 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet
|
|||||||
const val TAG = "Charts/ChartView"
|
const val TAG = "Charts/ChartView"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val rect = RectF()
|
|
||||||
|
|
||||||
private val debugStrokePaint = Paint().apply {
|
|
||||||
style = Paint.Style.STROKE
|
|
||||||
strokeWidth = 8f
|
|
||||||
color = Color.parseColor("#654321")
|
|
||||||
}
|
|
||||||
|
|
||||||
override var debug: Boolean = false
|
override var debug: Boolean = false
|
||||||
|
|
||||||
override val xAxis = XAxis(this)
|
override val xAxis = XAxis(this)
|
||||||
@ -37,43 +29,13 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet
|
|||||||
|
|
||||||
override var series: ArrayList<SerieInterface> = arrayListOf()
|
override var series: ArrayList<SerieInterface> = arrayListOf()
|
||||||
|
|
||||||
override fun refresh() {
|
override var padding: Float = 8f
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
private val scroller = ChartScroll(this).apply {
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
// draw corners
|
|
||||||
canvas.drawRect(rect.apply {
|
|
||||||
set(8f, 8f, width - 8f, height - 8f)
|
|
||||||
}, debugStrokePaint)
|
|
||||||
}
|
|
||||||
|
|
||||||
// right distance from the yAxis
|
|
||||||
val rightDistance = yAxis.onDraw(canvas)
|
|
||||||
|
|
||||||
// chart draw rectangle
|
|
||||||
rect.apply {
|
|
||||||
set(0f, 8f, width.toFloat() - 16f - rightDistance, height.toFloat() - 16f)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (serie in series) {
|
|
||||||
serie.onDraw(canvas, rect)
|
|
||||||
}
|
|
||||||
super.onDraw(canvas)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
||||||
performClick()
|
|
||||||
return scroller.onTouchEvent(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
val scroller = ChartScroll(this).apply {
|
|
||||||
var lastMovement = 0.0
|
var lastMovement = 0.0
|
||||||
setOnChartMoved { movementX, _ ->
|
setOnChartMoved { movementX, _ ->
|
||||||
|
|
||||||
Log.d(TAG, "scrolled: ${(movementX - lastMovement) * (xAxis.increment / 10)}")
|
// Log.d(TAG, "scrolled: ${(movementX - lastMovement) * (xAxis.increment / 10)}")
|
||||||
xAxis.x = xAxis.x + (movementX - lastMovement) * (xAxis.increment / 10)
|
xAxis.x = xAxis.x + (movementX - lastMovement) * (xAxis.increment / 10)
|
||||||
lastMovement = movementX.toDouble()
|
lastMovement = movementX.toDouble()
|
||||||
refresh()
|
refresh()
|
||||||
@ -84,4 +46,98 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet
|
|||||||
// refresh()
|
// refresh()
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// val animator: Runnable = object : Runnable {
|
||||||
|
// override fun run() {
|
||||||
|
// var needNewFrame = false
|
||||||
|
// for (serie in series) {
|
||||||
|
// val result = serie.onUpdate()
|
||||||
|
// if (result) {
|
||||||
|
// needNewFrame = true
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (needNewFrame) {
|
||||||
|
// postDelayed(this, animation.getDelay().toLong())
|
||||||
|
// }
|
||||||
|
// invalidate()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// rect used for calculations
|
||||||
|
private val rect = RectF()
|
||||||
|
|
||||||
|
// stroke used while in debug
|
||||||
|
private val debugStrokePaint = Paint().apply {
|
||||||
|
style = Paint.Style.STROKE
|
||||||
|
strokeWidth = 8f
|
||||||
|
color = Color.parseColor("#654321")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
// run Axis logics
|
||||||
|
xAxis.refresh()
|
||||||
|
yAxis.refresh()
|
||||||
|
|
||||||
|
// run series logic
|
||||||
|
for (serie in series) {
|
||||||
|
serie.refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
// invalidate the view
|
||||||
|
invalidate()
|
||||||
|
// removeCallbacks(animator)
|
||||||
|
// post(animator)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas) {
|
||||||
|
|
||||||
|
// don't draw anything if everything is empty
|
||||||
|
if (series.isEmpty() || series.maxOf { it.entries.size } == 0) {
|
||||||
|
super.onDraw(canvas)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
// draw corners
|
||||||
|
canvas.drawRect(rect.apply {
|
||||||
|
set(
|
||||||
|
padding / 2,
|
||||||
|
padding / 2,
|
||||||
|
width.toFloat() - padding / 2,
|
||||||
|
height.toFloat() - padding / 2
|
||||||
|
)
|
||||||
|
}, debugStrokePaint)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val bottom = xAxis.onDraw(canvas, rect.apply {
|
||||||
|
set(padding, 0f, width.toFloat() - padding, height.toFloat() - padding)
|
||||||
|
})
|
||||||
|
|
||||||
|
// right distance from the yAxis
|
||||||
|
val rightDistance = yAxis.onDraw(canvas, rect.apply {
|
||||||
|
set(padding, padding, width.toFloat() - padding, height.toFloat() - bottom - padding)
|
||||||
|
})
|
||||||
|
|
||||||
|
// chart draw rectangle
|
||||||
|
rect.apply {
|
||||||
|
set(
|
||||||
|
padding,
|
||||||
|
padding,
|
||||||
|
width.toFloat() - padding - rightDistance,
|
||||||
|
height - bottom - padding
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (serie in series) {
|
||||||
|
serie.onDraw(canvas, rect)
|
||||||
|
}
|
||||||
|
super.onDraw(canvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
performClick()
|
||||||
|
return scroller.onTouchEvent(event)
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,166 +0,0 @@
|
|||||||
package com.dzeio.charts
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.graphics.RectF
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
|
||||||
import com.dzeio.charts.axis.XAxis
|
|
||||||
import com.dzeio.charts.axis.YAxis
|
|
||||||
import com.dzeio.charts.components.ChartScroll
|
|
||||||
import com.dzeio.charts.series.SerieAbstract
|
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
|
|
||||||
View(context, attrs) {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val TAG = "DzeioCharts/ChartView"
|
|
||||||
}
|
|
||||||
|
|
||||||
override var debug = false
|
|
||||||
|
|
||||||
override val xAxis = XAxis<Float>()
|
|
||||||
|
|
||||||
override val yAxis = YAxis(this)
|
|
||||||
|
|
||||||
override val animation = Animation()
|
|
||||||
|
|
||||||
override val scroller = ChartScroll(this).apply {
|
|
||||||
setOnChartMoved { movementX, _ ->
|
|
||||||
// Log.d(TAG, "scrolled: $movementX")
|
|
||||||
movementOffset = movementX / 100
|
|
||||||
refresh()
|
|
||||||
}
|
|
||||||
setOnZoomChanged {
|
|
||||||
Log.d(TAG, "New Zoom: $it")
|
|
||||||
zoom = (it * 1.2).toFloat()
|
|
||||||
refresh()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val animator: Runnable = object : Runnable {
|
|
||||||
override fun run() {
|
|
||||||
var needNewFrame = false
|
|
||||||
for (serie in series) {
|
|
||||||
val result = serie.onUpdate()
|
|
||||||
if (result) {
|
|
||||||
needNewFrame = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (needNewFrame) {
|
|
||||||
postDelayed(this, animation.getDelay().toLong())
|
|
||||||
}
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* global padding
|
|
||||||
*/
|
|
||||||
override var padding: Float = 8f
|
|
||||||
|
|
||||||
override var series: ArrayList<SerieAbstract> = arrayListOf()
|
|
||||||
set(value) {
|
|
||||||
for (serie in value) {
|
|
||||||
serie.view = this
|
|
||||||
}
|
|
||||||
field = value
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of entries displayed at the same time
|
|
||||||
*/
|
|
||||||
override var zoom = 100f
|
|
||||||
|
|
||||||
override var movementOffset: Float = 0f
|
|
||||||
|
|
||||||
override val rectF = RectF()
|
|
||||||
override val otherUseRectF = RectF()
|
|
||||||
|
|
||||||
override fun refresh() {
|
|
||||||
for (serie in series) {
|
|
||||||
serie.prepareData()
|
|
||||||
}
|
|
||||||
rectF.set(
|
|
||||||
padding,
|
|
||||||
padding,
|
|
||||||
measuredWidth - padding - yAxis.getWidth() - padding,
|
|
||||||
height - padding
|
|
||||||
)
|
|
||||||
|
|
||||||
removeCallbacks(animator)
|
|
||||||
post(animator)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val fgPaint: Paint = Paint().also {
|
|
||||||
it.isAntiAlias = true
|
|
||||||
it.color = Color.parseColor("#123456")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas) {
|
|
||||||
|
|
||||||
if (yAxis.legendEnabled) {
|
|
||||||
yAxis.display(canvas, measuredWidth, height)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (serie in series) {
|
|
||||||
serie.displayData(canvas, rectF)
|
|
||||||
}
|
|
||||||
// canvas.drawRect(
|
|
||||||
// measuredWidth - padding - yAxis.getWidth(),
|
|
||||||
// 0f,
|
|
||||||
// measuredWidth - padding,
|
|
||||||
// height - padding,
|
|
||||||
// fgPaint
|
|
||||||
// )
|
|
||||||
super.onDraw(canvas)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
|
||||||
performClick()
|
|
||||||
return scroller.onTouchEvent(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getXOffset(): Int {
|
|
||||||
// Log.d(
|
|
||||||
// TAG,
|
|
||||||
// "baseOffset: ${xAxis.baseOffset}, mOffset: $movementOffset = ${xAxis.baseOffset + movementOffset}"
|
|
||||||
// )
|
|
||||||
// Log.d(
|
|
||||||
// TAG,
|
|
||||||
// "longestOffset: ${longestSerie()}, displayedEntries: ${getDisplayedEntries()} = ${longestSerie() - getDisplayedEntries()}"
|
|
||||||
// )
|
|
||||||
return min(
|
|
||||||
max(0f, xAxis.baseOffset + movementOffset).toInt(),
|
|
||||||
max(0, getCalculatedMax() - getDisplayedEntries())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getDisplayedEntries(): Int {
|
|
||||||
// Log.d(TAG, "Number of entries displayed ${list.size}, ${xAxis.entriesDisplayed} + (($zoom - 100) * 10) = ${xAxis.entriesDisplayed + ((zoom - 100) * 10).toInt()}")
|
|
||||||
return max(0, xAxis.entriesDisplayed + ((zoom - 100) * 10).toInt())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getCalculatedMax(): Int {
|
|
||||||
var size = 0
|
|
||||||
for (serie in series) {
|
|
||||||
if (serie.datas.size > size) size = serie.datas.size
|
|
||||||
}
|
|
||||||
return size
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getXMax(displayedOnly: Boolean): Float {
|
|
||||||
var max = 0f
|
|
||||||
for (serie in series) {
|
|
||||||
val res = serie.getYMax(displayedOnly)
|
|
||||||
if (max < res) max = res
|
|
||||||
}
|
|
||||||
return max
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,6 +13,11 @@ interface ChartViewInterface {
|
|||||||
*/
|
*/
|
||||||
var debug: Boolean
|
var debug: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the padding inside the view
|
||||||
|
*/
|
||||||
|
var padding: Float
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hold metadata about the X axis
|
* Hold metadata about the X axis
|
||||||
*/
|
*/
|
||||||
@ -29,7 +34,9 @@ interface ChartViewInterface {
|
|||||||
var series: ArrayList<SerieInterface>
|
var series: ArrayList<SerieInterface>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* refresh the chart
|
* refresh and run pre-display logic the chart
|
||||||
|
*
|
||||||
|
* this function should be run if you change parameters in the view
|
||||||
*/
|
*/
|
||||||
fun refresh()
|
fun refresh()
|
||||||
}
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package com.dzeio.charts
|
package com.dzeio.charts
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Base entry for any charts
|
||||||
|
*/
|
||||||
data class Entry(
|
data class Entry(
|
||||||
val x: Double,
|
val x: Double,
|
||||||
val y: Float
|
val y: Float
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package com.dzeio.charts.axis
|
package com.dzeio.charts.axis
|
||||||
|
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.Rect
|
||||||
import android.graphics.RectF
|
import android.graphics.RectF
|
||||||
import com.dzeio.charts.ChartViewInterface
|
import com.dzeio.charts.ChartViewInterface
|
||||||
import com.dzeio.charts.Entry
|
import com.dzeio.charts.Entry
|
||||||
@ -23,9 +27,20 @@ class XAxis(
|
|||||||
|
|
||||||
field = value
|
field = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var enabled = true
|
||||||
override var increment: Double = 1.0
|
override var increment: Double = 1.0
|
||||||
override var displayCount: Int = 10
|
override var displayCount: Int = 10
|
||||||
override var labelCount: Int = 3
|
override var labelCount: Int = 2
|
||||||
|
|
||||||
|
override val textPaint = Paint().apply {
|
||||||
|
isAntiAlias = true
|
||||||
|
color = Color.parseColor("#FC496D")
|
||||||
|
textSize = 30f
|
||||||
|
textAlign = Paint.Align.LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
private val rect = Rect()
|
||||||
|
|
||||||
override fun getPositionOnRect(entry: Entry, rect: RectF): Double {
|
override fun getPositionOnRect(entry: Entry, rect: RectF): Double {
|
||||||
return translatePositionToRect(entry.x, rect)
|
return translatePositionToRect(entry.x, rect)
|
||||||
@ -52,5 +67,40 @@ class XAxis(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var onValueFormat: (value: Double) -> String = { it -> it.toString() }
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas, space: RectF): Float {
|
||||||
|
if (!enabled) {
|
||||||
|
return 0f
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxHeight = 0f
|
||||||
|
|
||||||
|
val graphIncrement = space.width() / (labelCount - 1)
|
||||||
|
val valueIncrement = (displayCount * increment / (labelCount - 1)).toDouble()
|
||||||
|
for (index in 0 until labelCount) {
|
||||||
|
val text = onValueFormat(x + valueIncrement * index)
|
||||||
|
textPaint.getTextBounds(text, 0, text.length, rect)
|
||||||
|
maxHeight = maxHeight.coerceAtLeast(rect.height().toFloat() + 1)
|
||||||
|
|
||||||
|
var xPos = space.left + graphIncrement * index
|
||||||
|
|
||||||
|
if (xPos + rect.width() > space.right) {
|
||||||
|
xPos = space.right - rect.width()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
canvas.drawText(
|
||||||
|
text,
|
||||||
|
xPos,
|
||||||
|
space.bottom,
|
||||||
|
textPaint
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return maxHeight + 32f
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,25 +0,0 @@
|
|||||||
package com.dzeio.charts.axis
|
|
||||||
|
|
||||||
import com.dzeio.charts.XAxisLabels
|
|
||||||
|
|
||||||
class XAxis<T> {
|
|
||||||
|
|
||||||
var max: T? = null
|
|
||||||
var min: T? = null
|
|
||||||
|
|
||||||
val labels = XAxisLabels()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of entries displayed in the chart at the same time
|
|
||||||
*/
|
|
||||||
var entriesDisplayed = 5
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Offset in the list
|
|
||||||
*/
|
|
||||||
var baseOffset = 0
|
|
||||||
|
|
||||||
var onValueFormat: (it: T) -> String = onValueFormat@{
|
|
||||||
return@onValueFormat it.toString()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,17 @@
|
|||||||
package com.dzeio.charts.axis
|
package com.dzeio.charts.axis
|
||||||
|
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Paint
|
||||||
import android.graphics.RectF
|
import android.graphics.RectF
|
||||||
import com.dzeio.charts.Entry
|
import com.dzeio.charts.Entry
|
||||||
|
|
||||||
sealed interface XAxisInterface {
|
sealed interface XAxisInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enable/disable the display of the xAxis
|
||||||
|
*/
|
||||||
|
var enabled: Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set X position
|
* set X position
|
||||||
*/
|
*/
|
||||||
@ -15,6 +22,11 @@ sealed interface XAxisInterface {
|
|||||||
*/
|
*/
|
||||||
var increment: Double
|
var increment: Double
|
||||||
|
|
||||||
|
/**
|
||||||
|
* text Paint
|
||||||
|
*/
|
||||||
|
val textPaint: Paint
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* indicate the max number of entries are displayed
|
* indicate the max number of entries are displayed
|
||||||
*/
|
*/
|
||||||
@ -25,11 +37,42 @@ sealed interface XAxisInterface {
|
|||||||
*/
|
*/
|
||||||
var labelCount: Int
|
var labelCount: Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* run when manually refreshing the system
|
||||||
|
*
|
||||||
|
* this is where the pre-logic is handled to make [onDraw] quicker
|
||||||
|
*/
|
||||||
|
fun refresh()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the entry position on the rect
|
||||||
|
*
|
||||||
|
* @return the left side of the position of the entry
|
||||||
|
*/
|
||||||
fun getPositionOnRect(entry: Entry, rect: RectF): Double
|
fun getPositionOnRect(entry: Entry, rect: RectF): Double
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the graph offset for X (kinda like [getPositionOnRect])
|
||||||
|
*/
|
||||||
fun getXOffset(rect: RectF): Double
|
fun getXOffset(rect: RectF): Double
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the maximum the X can get to
|
||||||
|
*/
|
||||||
fun getXMax(): Double
|
fun getXMax(): Double
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the minimum the X can get to
|
||||||
|
*/
|
||||||
fun getXMin(): Double
|
fun getXMin(): Double
|
||||||
|
|
||||||
|
/**
|
||||||
|
* onDraw event that will draw the XAxis
|
||||||
|
*
|
||||||
|
* @param canvas the canvas to draw on
|
||||||
|
* @param space the space where it is allowed to draw
|
||||||
|
*
|
||||||
|
* @return the final height of the XAxis
|
||||||
|
*/
|
||||||
|
fun onDraw(canvas: Canvas, space: RectF): Float
|
||||||
}
|
}
|
@ -4,8 +4,8 @@ import android.graphics.Canvas
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
import android.graphics.RectF
|
||||||
import com.dzeio.charts.ChartViewInterface
|
import com.dzeio.charts.ChartViewInterface
|
||||||
import com.dzeio.charts.utils.drawDottedLine
|
|
||||||
|
|
||||||
class YAxis(
|
class YAxis(
|
||||||
private val view: ChartViewInterface
|
private val view: ChartViewInterface
|
||||||
@ -25,11 +25,11 @@ class YAxis(
|
|||||||
color = Color.BLUE
|
color = Color.BLUE
|
||||||
}
|
}
|
||||||
|
|
||||||
var onValueFormat: (value: Float) -> String = { it -> it.toString()}
|
var onValueFormat: (value: Float) -> String = { it -> it.toString() }
|
||||||
|
|
||||||
override var labelCount: Int = 3
|
override var labelCount = 5
|
||||||
|
|
||||||
private var min: Float? = null
|
private var min: Float? = 0f
|
||||||
private var max: Float? = null
|
private var max: Float? = null
|
||||||
|
|
||||||
private val rect = Rect()
|
private val rect = Rect()
|
||||||
@ -76,14 +76,14 @@ class YAxis(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDraw(canvas: Canvas): Float {
|
override fun onDraw(canvas: Canvas, space: RectF): Float {
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return 0f
|
return 0f
|
||||||
}
|
}
|
||||||
val min = getYMin()
|
val min = getYMin()
|
||||||
val max = getYMax() - min
|
val max = getYMax() - min
|
||||||
val top = 0
|
val top = space.top
|
||||||
val bottom = canvas.height.toFloat()
|
val bottom = space.bottom
|
||||||
var maxWidth = 0f
|
var maxWidth = 0f
|
||||||
|
|
||||||
val increment = (bottom - top) / labelCount
|
val increment = (bottom - top) / labelCount
|
||||||
@ -97,13 +97,18 @@ class YAxis(
|
|||||||
|
|
||||||
canvas.drawText(
|
canvas.drawText(
|
||||||
text,
|
text,
|
||||||
canvas.width - rect.width().toFloat(),
|
space.width() - rect.width().toFloat(),
|
||||||
posY + rect.height() + 8f,
|
(posY + rect.height() / 2).coerceAtLeast(rect.height().toFloat()),
|
||||||
textLabel
|
textLabel
|
||||||
)
|
)
|
||||||
canvas.drawDottedLine(0f, posY, canvas.width.toFloat(), posY, 40f, linePaint)
|
// canvas.drawDottedLine(0f, posY, canvas.width.toFloat(), posY, 40f, linePaint)
|
||||||
|
canvas.drawLine(space.left, posY, space.right - maxWidth - 32f, posY, linePaint)
|
||||||
|
|
||||||
}
|
}
|
||||||
return maxWidth
|
return maxWidth + 32f
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,74 +0,0 @@
|
|||||||
package com.dzeio.charts.axis
|
|
||||||
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.graphics.Rect
|
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import com.dzeio.charts.ChartView
|
|
||||||
import com.dzeio.charts.utils.drawDottedLine
|
|
||||||
|
|
||||||
class YAxis<T>(
|
|
||||||
private val chartView: ChartView
|
|
||||||
) {
|
|
||||||
var max: T? = null
|
|
||||||
var min: T? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of labels displayed on the sidebar
|
|
||||||
*/
|
|
||||||
var labelCount: Int = 4
|
|
||||||
|
|
||||||
@ColorInt
|
|
||||||
var color = Color.parseColor("#FC496D")
|
|
||||||
|
|
||||||
var textPaint: Paint = Paint().also {
|
|
||||||
it.isAntiAlias = true
|
|
||||||
it.color = color
|
|
||||||
it.textSize = 30f
|
|
||||||
it.textAlign = Paint.Align.RIGHT
|
|
||||||
}
|
|
||||||
|
|
||||||
var linePaint = Paint().apply {
|
|
||||||
isAntiAlias = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var legendEnabled = true
|
|
||||||
|
|
||||||
private val rect: Rect = Rect()
|
|
||||||
|
|
||||||
fun getWidth(): Int {
|
|
||||||
var maxWidth = 0
|
|
||||||
val max = chartView.getXMax(true)
|
|
||||||
val vIncrement = max / labelCount
|
|
||||||
for (i in 0 until labelCount) {
|
|
||||||
val text = onValueFormat(vIncrement * (labelCount - i), true)
|
|
||||||
textPaint.getTextBounds(text, 0, text.length, rect)
|
|
||||||
if (rect.width() > maxWidth) maxWidth = rect.width()
|
|
||||||
}
|
|
||||||
return maxWidth + chartView.padding.toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to display the YAxis sidebar on the right
|
|
||||||
*
|
|
||||||
* it migh also display content over the Graph
|
|
||||||
*/
|
|
||||||
fun display(canvas: Canvas, width: Int, height: Int) {
|
|
||||||
val max = chartView.getXMax(true)
|
|
||||||
val increment = (height - chartView.padding * 2) / labelCount
|
|
||||||
val vIncrement = max / labelCount
|
|
||||||
for (i in 0 until labelCount) {
|
|
||||||
val text = onValueFormat(vIncrement * (labelCount - i), true)
|
|
||||||
textPaint.getTextBounds(text, 0, text.length, rect)
|
|
||||||
val posY = increment * i.toFloat()
|
|
||||||
canvas.drawDottedLine(0f, posY + chartView.padding, width - rect.width().toFloat() - chartView.padding, posY, 40f, linePaint)
|
|
||||||
canvas.drawText(text,
|
|
||||||
width.toFloat() - chartView.padding, posY + chartView.padding, textPaint)
|
|
||||||
// canvas.drawDottedLine(0f, posY, measuredWidth.toFloat(), posY, 10f, linePaint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var onValueFormat: (value: Float, shortVersion: Boolean) -> String = { it, _ -> it.toString() }
|
|
||||||
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package com.dzeio.charts.axis
|
|||||||
|
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
|
import android.graphics.RectF
|
||||||
|
|
||||||
sealed interface YAxisInterface {
|
sealed interface YAxisInterface {
|
||||||
|
|
||||||
@ -10,6 +11,30 @@ sealed interface YAxisInterface {
|
|||||||
*/
|
*/
|
||||||
var enabled: Boolean
|
var enabled: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get/set the number of label of this Y axis
|
||||||
|
*
|
||||||
|
* the first/last labels are at the bottom/top of the chart
|
||||||
|
*/
|
||||||
|
var labelCount: Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* text label paint
|
||||||
|
*/
|
||||||
|
val textLabel: Paint
|
||||||
|
|
||||||
|
/**
|
||||||
|
* paint for the lines
|
||||||
|
*/
|
||||||
|
val linePaint: Paint
|
||||||
|
|
||||||
|
/**
|
||||||
|
* run when manually refreshing the system
|
||||||
|
*
|
||||||
|
* this is where the pre-logic is handled to make [onDraw] quicker
|
||||||
|
*/
|
||||||
|
fun refresh()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* override Y minimum
|
* override Y minimum
|
||||||
*
|
*
|
||||||
@ -38,27 +63,13 @@ sealed interface YAxisInterface {
|
|||||||
*/
|
*/
|
||||||
fun getYMin(): Float
|
fun getYMin(): Float
|
||||||
|
|
||||||
/**
|
|
||||||
* get/set the number of label of this Y axis
|
|
||||||
*
|
|
||||||
* the first/last labels are at the bottom/top of the chart
|
|
||||||
*/
|
|
||||||
var labelCount: Int
|
|
||||||
|
|
||||||
/**
|
|
||||||
* text label paint
|
|
||||||
*/
|
|
||||||
val textLabel: Paint
|
|
||||||
|
|
||||||
/**
|
|
||||||
* paint for the dotted line
|
|
||||||
*/
|
|
||||||
val linePaint: Paint
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* function that draw our legend
|
* function that draw our legend
|
||||||
*
|
*
|
||||||
|
* @param canvas the canvas to draw on
|
||||||
|
* @param space the space where it is allowed to draw on
|
||||||
|
*
|
||||||
* @return the width of the sidebar
|
* @return the width of the sidebar
|
||||||
*/
|
*/
|
||||||
fun onDraw(canvas: Canvas): Float
|
fun onDraw(canvas: Canvas, space: RectF): Float
|
||||||
}
|
}
|
@ -1,5 +1,10 @@
|
|||||||
package com.dzeio.charts.axis
|
package com.dzeio.charts.axis
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CURRENTLY UNUSED
|
||||||
|
*
|
||||||
|
* declare where the YAxis for the graph will be
|
||||||
|
*/
|
||||||
enum class YAxisPosition {
|
enum class YAxisPosition {
|
||||||
LEFT,
|
LEFT,
|
||||||
RIGHT
|
RIGHT
|
||||||
|
@ -5,6 +5,9 @@ import android.view.MotionEvent.INVALID_POINTER_ID
|
|||||||
import android.view.ScaleGestureDetector
|
import android.view.ScaleGestureDetector
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class handling the scroll/zoom for the library
|
||||||
|
*/
|
||||||
class ChartScroll(view: View) {
|
class ChartScroll(view: View) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package com.dzeio.charts.series
|
package com.dzeio.charts.series
|
||||||
|
|
||||||
import android.graphics.*
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.graphics.RectF
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.dzeio.charts.ChartView
|
import com.dzeio.charts.ChartView
|
||||||
import com.dzeio.charts.utils.drawRoundRect
|
import com.dzeio.charts.utils.drawRoundRect
|
||||||
@ -13,6 +17,10 @@ class BarSerie(
|
|||||||
const val TAG = "Charts/BarSerie"
|
const val TAG = "Charts/BarSerie"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
view.series.add(this)
|
||||||
|
}
|
||||||
|
|
||||||
val barPaint = Paint().apply {
|
val barPaint = Paint().apply {
|
||||||
isAntiAlias = true
|
isAntiAlias = true
|
||||||
color = Color.parseColor("#123456")
|
color = Color.parseColor("#123456")
|
||||||
@ -38,8 +46,8 @@ class BarSerie(
|
|||||||
|
|
||||||
for (entry in displayedEntries) {
|
for (entry in displayedEntries) {
|
||||||
// calculated height in percent from 0 to 100
|
// calculated height in percent from 0 to 100
|
||||||
val top = (1 - entry.y / max) * drawableSpace.height()
|
val top = (1 - entry.y / max) * drawableSpace.height() + drawableSpace.top
|
||||||
val posX = (view.xAxis.getPositionOnRect(entry, drawableSpace) - view.xAxis.getXOffset(drawableSpace)).toFloat()
|
var posX = drawableSpace.left + (view.xAxis.getPositionOnRect(entry, drawableSpace) - view.xAxis.getXOffset(drawableSpace)).toFloat()
|
||||||
// Log.d(TAG, "gpor = ${view.xAxis.getPositionOnRect(entry, space)}, gxo = ${view.xAxis.getXOffset(space)}")
|
// Log.d(TAG, "gpor = ${view.xAxis.getPositionOnRect(entry, space)}, gxo = ${view.xAxis.getXOffset(space)}")
|
||||||
// Log.d(TAG, "max = $max, y = ${entry.y}, height = $height")
|
// Log.d(TAG, "max = $max, y = ${entry.y}, height = $height")
|
||||||
// Log.d(TAG, "posX: ${posX / 60 / 60 / 1000}, offsetX = ${view.xAxis.x / (1000 * 60 * 60)}, x = ${entry.x / (1000 * 60 * 60)}, pouet: ${(view.xAxis.x + view.xAxis.displayCount * view.xAxis.increment) / (1000 * 60 * 60)}")
|
// Log.d(TAG, "posX: ${posX / 60 / 60 / 1000}, offsetX = ${view.xAxis.x / (1000 * 60 * 60)}, x = ${entry.x / (1000 * 60 * 60)}, pouet: ${(view.xAxis.x + view.xAxis.displayCount * view.xAxis.increment) / (1000 * 60 * 60)}")
|
||||||
@ -48,14 +56,20 @@ class BarSerie(
|
|||||||
TAG, """
|
TAG, """
|
||||||
${posX},
|
${posX},
|
||||||
$top,
|
$top,
|
||||||
${(posX + barWidth).toFloat()},
|
${(posX + barWidth)},
|
||||||
${drawableSpace.bottom}""".trimIndent()
|
${drawableSpace.bottom}""".trimIndent()
|
||||||
)
|
)
|
||||||
|
|
||||||
val right = (posX + barWidth).toFloat().coerceAtMost(drawableSpace.right)
|
val right = (posX + barWidth).coerceAtMost(drawableSpace.right)
|
||||||
|
|
||||||
if (posX > right) {
|
if (posX > right) {
|
||||||
continue
|
continue
|
||||||
|
} else if (posX < drawableSpace.left) {
|
||||||
|
posX = drawableSpace.left
|
||||||
|
}
|
||||||
|
|
||||||
|
if (right < drawableSpace.left) {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.drawRoundRect(
|
canvas.drawRoundRect(
|
||||||
@ -76,9 +90,14 @@ class BarSerie(
|
|||||||
|
|
||||||
textPaint.getTextBounds(text, 0, text.length, rect)
|
textPaint.getTextBounds(text, 0, text.length, rect)
|
||||||
|
|
||||||
val textLeft = (posX + barWidth / 2).toFloat()
|
val textLeft = (posX + barWidth / 2)
|
||||||
|
|
||||||
if (textLeft + rect.width() / 2 > right) {
|
if (
|
||||||
|
// handle right side
|
||||||
|
textLeft + rect.width() / 2 > right ||
|
||||||
|
// handle left sie
|
||||||
|
textLeft - rect.width() / 2 < drawableSpace.left
|
||||||
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,14 +105,23 @@ class BarSerie(
|
|||||||
rect.height() + 40f < drawableSpace.bottom - top &&
|
rect.height() + 40f < drawableSpace.bottom - top &&
|
||||||
rect.width() < barWidth
|
rect.width() < barWidth
|
||||||
|
|
||||||
|
var textY = if (doDisplayIn) top + rect.height() + 20f else top - 20f
|
||||||
|
|
||||||
|
if (textY < 0) {
|
||||||
|
textY = drawableSpace.top + rect.height()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
canvas.drawText(
|
canvas.drawText(
|
||||||
text,
|
text,
|
||||||
textLeft,
|
textLeft,
|
||||||
if (doDisplayIn) top + rect.height() + 20f else top - 20f,
|
textY,
|
||||||
textPaint
|
textPaint
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun refresh() {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,64 +0,0 @@
|
|||||||
package com.dzeio.charts.series
|
|
||||||
|
|
||||||
import android.graphics.Canvas
|
|
||||||
import android.graphics.RectF
|
|
||||||
import com.dzeio.charts.ChartView
|
|
||||||
import com.dzeio.charts.Entry
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
abstract class SerieAbstract {
|
|
||||||
|
|
||||||
var datas: ArrayList<Entry> = arrayListOf()
|
|
||||||
|
|
||||||
lateinit var view: ChartView
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get Serie Y max
|
|
||||||
*/
|
|
||||||
fun getYMax(displayedOnly: Boolean = false): Float {
|
|
||||||
var max = Float.MIN_VALUE
|
|
||||||
val localDatas = if (displayedOnly) getDisplayedEntries() else datas
|
|
||||||
for (data in localDatas) {
|
|
||||||
if (max < data.y) max = data.y
|
|
||||||
}
|
|
||||||
return max
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get Serie Y min
|
|
||||||
*/
|
|
||||||
fun getYMin(displayedOnly: Boolean = false): Float {
|
|
||||||
var min = Float.MAX_VALUE
|
|
||||||
val localDatas = if (displayedOnly) getDisplayedEntries() else datas
|
|
||||||
for (data in localDatas) {
|
|
||||||
if (min > data.y) min = data.y
|
|
||||||
}
|
|
||||||
return min
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Animation updates
|
|
||||||
*/
|
|
||||||
abstract fun onUpdate(): Boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to prepare for an update
|
|
||||||
*/
|
|
||||||
abstract fun prepareData()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to display data on the graph
|
|
||||||
*
|
|
||||||
* @param canvas the canvas to draw on
|
|
||||||
* @param rect the rectangle in which you have to draw data
|
|
||||||
*/
|
|
||||||
abstract fun displayData(canvas: Canvas, rect: RectF)
|
|
||||||
|
|
||||||
protected fun getDisplayedEntries(): MutableList<Entry> {
|
|
||||||
return datas.subList(
|
|
||||||
view.getXOffset(),
|
|
||||||
min(datas.size, view.getDisplayedEntries() + view.getXOffset())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,5 +24,18 @@ sealed interface SerieInterface {
|
|||||||
*/
|
*/
|
||||||
var entries: ArrayList<Entry>
|
var entries: ArrayList<Entry>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* function that display the graph
|
||||||
|
*
|
||||||
|
* @param canvas the canvas to draw on
|
||||||
|
* @param drawableSpace the space you are allowed to draw on
|
||||||
|
*/
|
||||||
fun onDraw(canvas: Canvas, drawableSpace: RectF)
|
fun onDraw(canvas: Canvas, drawableSpace: RectF)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* run when manually refreshing the system
|
||||||
|
*
|
||||||
|
* this is where the pre-logic is handled to make [onDraw] quicker
|
||||||
|
*/
|
||||||
|
fun refresh()
|
||||||
}
|
}
|
@ -5,6 +5,9 @@ import android.graphics.Paint
|
|||||||
import android.graphics.RectF
|
import android.graphics.RectF
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
/**
|
||||||
|
* draw a dotted line
|
||||||
|
*/
|
||||||
fun Canvas.drawDottedLine(
|
fun Canvas.drawDottedLine(
|
||||||
startX: Float,
|
startX: Float,
|
||||||
startY: Float,
|
startY: Float,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user