mirror of
https://github.com/dzeiocom/OpenHealth.git
synced 2025-04-23 11:22:10 +00:00
feat(charts): Moved to modules based charts
Signed-off-by: Avior <github@avior.me>
This commit is contained in:
parent
c2bc9eced2
commit
f6b5715572
@ -1,13 +1,13 @@
|
|||||||
package com.dzeio.openhealth.ui.steps
|
package com.dzeio.openhealth.ui.steps
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.widget.NestedScrollView
|
import androidx.core.widget.NestedScrollView
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.dzeio.charts.Entry
|
import com.dzeio.charts.Entry
|
||||||
|
import com.dzeio.charts.series.BarSerie
|
||||||
import com.dzeio.openhealth.Application
|
import com.dzeio.openhealth.Application
|
||||||
import com.dzeio.openhealth.R
|
import com.dzeio.openhealth.R
|
||||||
import com.dzeio.openhealth.adapters.StepsAdapter
|
import com.dzeio.openhealth.adapters.StepsAdapter
|
||||||
@ -52,10 +52,17 @@ class StepsHomeFragment :
|
|||||||
|
|
||||||
val chart = binding.chart
|
val chart = binding.chart
|
||||||
|
|
||||||
|
val serie = BarSerie()
|
||||||
|
|
||||||
|
chart.series = arrayListOf(serie)
|
||||||
|
|
||||||
viewModel.items.observe(viewLifecycleOwner) { list ->
|
viewModel.items.observe(viewLifecycleOwner) { list ->
|
||||||
adapter.set(list)
|
adapter.set(list)
|
||||||
chart.xAxis.entriesDisplayed = 30
|
|
||||||
chart.numberOfLabels = 2
|
chart.debug = true
|
||||||
|
|
||||||
|
chart.xAxis.entriesDisplayed = 10
|
||||||
|
// chart.numberOfLabels = 2
|
||||||
|
|
||||||
// chart.animation.enabled = false
|
// chart.animation.enabled = false
|
||||||
chart.animation.refreshRate = 60
|
chart.animation.refreshRate = 60
|
||||||
@ -71,7 +78,7 @@ class StepsHomeFragment :
|
|||||||
com.google.android.material.R.attr.colorPrimary
|
com.google.android.material.R.attr.colorPrimary
|
||||||
)
|
)
|
||||||
|
|
||||||
chart.list = list.reversed().map {
|
serie.datas = list.reversed().map {
|
||||||
return@map Entry(it.timestamp.toDouble(), it.value.toFloat())
|
return@map Entry(it.timestamp.toDouble(), it.value.toFloat())
|
||||||
} as ArrayList<Entry>
|
} as ArrayList<Entry>
|
||||||
|
|
||||||
@ -88,21 +95,5 @@ class StepsHomeFragment :
|
|||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<view
|
<view
|
||||||
class="com.dzeio.charts.views.BarChartView"
|
class="com.dzeio.charts.ChartView"
|
||||||
android:id="@+id/chart"
|
android:id="@+id/chart"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="200dp"
|
android:layout_height="200dp"
|
||||||
|
152
charts/src/main/java/com/dzeio/charts/ChartView.kt
Normal file
152
charts/src/main/java/com/dzeio/charts/ChartView.kt
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
var debug = false
|
||||||
|
|
||||||
|
val xAxis = XAxis<Float>()
|
||||||
|
|
||||||
|
val yAxis = YAxis<Float>()
|
||||||
|
|
||||||
|
val animation = Animation()
|
||||||
|
|
||||||
|
val scroller = ChartScroll(this).apply {
|
||||||
|
setOnChartMoved { movementX, movementY ->
|
||||||
|
// Log.d(TAG, "scrolled: $movementX")
|
||||||
|
movementOffset = movementX / 100
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
setOnZoomChanged {
|
||||||
|
Log.d(TAG, "New Zoom: $it")
|
||||||
|
zoom = (it * 1.2).toFloat()
|
||||||
|
refresh()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private 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
|
||||||
|
*/
|
||||||
|
var padding: Float = 8f
|
||||||
|
|
||||||
|
var series: ArrayList<SerieAbstract> = arrayListOf()
|
||||||
|
set(value) {
|
||||||
|
for (serie in value) {
|
||||||
|
serie.view = this
|
||||||
|
}
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of entries displayed at the same time
|
||||||
|
*/
|
||||||
|
private var zoom = 100f
|
||||||
|
|
||||||
|
var movementOffset: Float = 0f
|
||||||
|
|
||||||
|
private val rectF = RectF()
|
||||||
|
private val otherUseRectF = RectF()
|
||||||
|
|
||||||
|
fun refresh() {
|
||||||
|
for (serie in series) {
|
||||||
|
serie.prepareData()
|
||||||
|
}
|
||||||
|
rectF.set(
|
||||||
|
padding,
|
||||||
|
padding,
|
||||||
|
measuredWidth - padding - yAxis.getWidth(longestSerie().toFloat()) - padding,
|
||||||
|
height - padding
|
||||||
|
)
|
||||||
|
|
||||||
|
removeCallbacks(animator)
|
||||||
|
post(animator)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val fgPaint: Paint = Paint().also {
|
||||||
|
it.isAntiAlias = true
|
||||||
|
it.color = Color.parseColor("#123456")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDraw(canvas: Canvas) {
|
||||||
|
for (serie in series) {
|
||||||
|
serie.displayData(canvas, rectF)
|
||||||
|
}
|
||||||
|
canvas.drawRect(
|
||||||
|
measuredWidth - padding - yAxis.getWidth(longestSerie().toFloat()),
|
||||||
|
0f,
|
||||||
|
measuredWidth - padding,
|
||||||
|
height - padding,
|
||||||
|
fgPaint
|
||||||
|
)
|
||||||
|
super.onDraw(canvas)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
performClick()
|
||||||
|
return scroller.onTouchEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
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(),
|
||||||
|
longestSerie() - getDisplayedEntries()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun longestSerie(): Int {
|
||||||
|
var size = 0
|
||||||
|
for (serie in series) {
|
||||||
|
if (serie.datas.size > size) size = serie.datas.size
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package com.dzeio.charts.axis
|
package com.dzeio.charts.axis
|
||||||
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.Rect
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
|
|
||||||
class YAxis<T> {
|
class YAxis<T> {
|
||||||
@ -9,4 +11,20 @@ class YAxis<T> {
|
|||||||
|
|
||||||
@ColorInt
|
@ColorInt
|
||||||
var color = Color.parseColor("#FC496D")
|
var color = Color.parseColor("#FC496D")
|
||||||
|
|
||||||
|
var paint: Paint = Paint().also {
|
||||||
|
it.isAntiAlias = true
|
||||||
|
it.color = color
|
||||||
|
it.textSize = 30f
|
||||||
|
it.textAlign = Paint.Align.CENTER
|
||||||
|
}
|
||||||
|
|
||||||
|
var legendEnabled = true
|
||||||
|
|
||||||
|
private val rect: Rect = Rect()
|
||||||
|
|
||||||
|
fun getWidth(max: Float): Int {
|
||||||
|
paint.getTextBounds(max.toString(), 0, max.toString().length, rect)
|
||||||
|
return rect.width()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
package com.dzeio.charts.views
|
package com.dzeio.charts.components
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.MotionEvent.INVALID_POINTER_ID
|
import android.view.MotionEvent.INVALID_POINTER_ID
|
||||||
import android.view.ScaleGestureDetector
|
import android.view.ScaleGestureDetector
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
|
||||||
abstract class BaseChart @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
|
class ChartScroll(view: View) {
|
||||||
View(context, attrs) {
|
|
||||||
|
|
||||||
// The ‘active pointer’ is the one currently moving our object.
|
// The ‘active pointer’ is the one currently moving our object.
|
||||||
private var activePointerId = INVALID_POINTER_ID
|
private var activePointerId = INVALID_POINTER_ID
|
||||||
@ -22,23 +19,30 @@ abstract class BaseChart @JvmOverloads constructor(context: Context?, attrs: Att
|
|||||||
private var lastZoom: Float = 100f
|
private var lastZoom: Float = 100f
|
||||||
private var currentZoom: Float = 0f
|
private var currentZoom: Float = 0f
|
||||||
|
|
||||||
open fun onChartMoved(movementX: Float, movementY: Float) {}
|
private var onChartMoved: ((movementX: Float, movementY: Float) -> Unit)? = null
|
||||||
|
fun setOnChartMoved(fn: (movementX: Float, movementY: Float) -> Unit) {
|
||||||
|
onChartMoved = fn
|
||||||
|
}
|
||||||
|
|
||||||
|
private var onZoomChanged: ((scale: Float) -> Unit)? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param scale Float starting from 100%
|
* @param fn.scale Float starting from 100%
|
||||||
*
|
*
|
||||||
* 99-% zoom out,
|
* 99-% zoom out,
|
||||||
* 101+% zoom in
|
* 101+% zoom in
|
||||||
*/
|
*/
|
||||||
open fun onZoomChanged(scale: Float) {}
|
fun setOnZoomChanged(fn: (scale: Float) -> Unit) {
|
||||||
|
onZoomChanged = fn
|
||||||
|
}
|
||||||
|
|
||||||
private val scaleGestureDetector = ScaleGestureDetector(
|
private val scaleGestureDetector = ScaleGestureDetector(
|
||||||
context,
|
view.context,
|
||||||
object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
||||||
override fun onScale(detector: ScaleGestureDetector): Boolean {
|
override fun onScale(detector: ScaleGestureDetector): Boolean {
|
||||||
if (currentZoom != detector.scaleFactor) {
|
if (currentZoom != detector.scaleFactor) {
|
||||||
currentZoom = detector.scaleFactor
|
currentZoom = detector.scaleFactor
|
||||||
onZoomChanged(lastZoom + -currentZoom + 1)
|
onZoomChanged?.invoke(lastZoom + -currentZoom + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onScale(detector)
|
return super.onScale(detector)
|
||||||
@ -55,9 +59,7 @@ abstract class BaseChart @JvmOverloads constructor(context: Context?, attrs: Att
|
|||||||
/**
|
/**
|
||||||
* Code mostly stolen from https://developer.android.com/training/gestures/scale#drag
|
* Code mostly stolen from https://developer.android.com/training/gestures/scale#drag
|
||||||
*/
|
*/
|
||||||
override fun onTouchEvent(ev: MotionEvent): Boolean {
|
fun onTouchEvent(ev: MotionEvent): Boolean {
|
||||||
super.onTouchEvent(ev)
|
|
||||||
|
|
||||||
scaleGestureDetector.onTouchEvent(ev)
|
scaleGestureDetector.onTouchEvent(ev)
|
||||||
|
|
||||||
when (ev.actionMasked) {
|
when (ev.actionMasked) {
|
||||||
@ -84,7 +86,7 @@ abstract class BaseChart @JvmOverloads constructor(context: Context?, attrs: Att
|
|||||||
posX += x - lastTouchX
|
posX += x - lastTouchX
|
||||||
posY += y - lastTouchY
|
posY += y - lastTouchY
|
||||||
|
|
||||||
onChartMoved(-posX, posY)
|
onChartMoved?.invoke(-posX, posY)
|
||||||
|
|
||||||
// Remember this touch position for the next move event
|
// Remember this touch position for the next move event
|
||||||
lastTouchX = x
|
lastTouchX = x
|
15
charts/src/main/java/com/dzeio/charts/components/Sidebar.kt
Normal file
15
charts/src/main/java/com/dzeio/charts/components/Sidebar.kt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package com.dzeio.charts.components
|
||||||
|
|
||||||
|
import android.graphics.RectF
|
||||||
|
|
||||||
|
class Sidebar {
|
||||||
|
|
||||||
|
var enabled = true
|
||||||
|
|
||||||
|
private val rect: RectF = RectF()
|
||||||
|
|
||||||
|
fun refresh(max: Float) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
154
charts/src/main/java/com/dzeio/charts/series/BarSerie.kt
Normal file
154
charts/src/main/java/com/dzeio/charts/series/BarSerie.kt
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package com.dzeio.charts.series
|
||||||
|
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Paint
|
||||||
|
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
|
||||||
|
|
||||||
|
var targetPercentList = arrayListOf<Float>()
|
||||||
|
var percentList = arrayListOf<Float>()
|
||||||
|
|
||||||
|
private var fgPaint: Paint = Paint().also {
|
||||||
|
it.isAntiAlias = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var previousRefresh = 0
|
||||||
|
|
||||||
|
override fun onUpdate(): Boolean {
|
||||||
|
var needNewFrame = false
|
||||||
|
for (i in targetPercentList.indices) {
|
||||||
|
val value = view.animation.updateValue(
|
||||||
|
1f,
|
||||||
|
targetPercentList[i],
|
||||||
|
percentList[i],
|
||||||
|
0f,
|
||||||
|
0.01f
|
||||||
|
)
|
||||||
|
|
||||||
|
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 {
|
||||||
|
getMax()
|
||||||
|
}
|
||||||
|
|
||||||
|
targetPercentList = arrayListOf()
|
||||||
|
|
||||||
|
// Log.d(TAG, "offset: ${view.getXOffset()}, displayed: ${view.getDisplayedEntries()}")
|
||||||
|
for (item in datas.subList(
|
||||||
|
view.getXOffset(),
|
||||||
|
view.getXOffset() + view.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.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()
|
||||||
|
// Log.d(TAG, "$spacing, $i, $barWidth = $left")
|
||||||
|
val right = rect.left + (spacing + barWidth) * i.toFloat()
|
||||||
|
val bottom = rect.top + rect.height()
|
||||||
|
val top = (bottom - rect.top) * percentList[i - 1]
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
if (view.debug) {
|
||||||
|
canvas.drawText(
|
||||||
|
(getMax() - getMax() * targetPercentList[i - 1]).toString(),
|
||||||
|
left + (right - left) / 2,
|
||||||
|
top + (bottom - top) / 2,
|
||||||
|
view.xAxis.labels.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMax(): Float {
|
||||||
|
var calculatedMax = 0f
|
||||||
|
for (entry in datas.subList(
|
||||||
|
view.getXOffset(),
|
||||||
|
view.getDisplayedEntries() + view.getXOffset()
|
||||||
|
)) {
|
||||||
|
if (entry.y > calculatedMax) calculatedMax = entry.y
|
||||||
|
}
|
||||||
|
return if (calculatedMax < 0) 0f else calculatedMax
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.dzeio.charts.series
|
||||||
|
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.RectF
|
||||||
|
import com.dzeio.charts.ChartView
|
||||||
|
import com.dzeio.charts.Entry
|
||||||
|
|
||||||
|
abstract class SerieAbstract {
|
||||||
|
|
||||||
|
var datas: ArrayList<Entry> = arrayListOf()
|
||||||
|
|
||||||
|
lateinit var view: ChartView
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
}
|
@ -6,7 +6,7 @@ import android.graphics.Paint
|
|||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.RectF
|
import android.graphics.RectF
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
import android.view.View
|
||||||
import com.dzeio.charts.Animation
|
import com.dzeio.charts.Animation
|
||||||
import com.dzeio.charts.Entry
|
import com.dzeio.charts.Entry
|
||||||
import com.dzeio.charts.axis.XAxis
|
import com.dzeio.charts.axis.XAxis
|
||||||
@ -16,7 +16,7 @@ import kotlin.math.max
|
|||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class BarChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
|
class BarChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
|
||||||
BaseChart(context, attrs) {
|
View(context, attrs) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TAG = "DzeioCharts/BarView"
|
const val TAG = "DzeioCharts/BarView"
|
||||||
@ -263,16 +263,16 @@ class BarChartView @JvmOverloads constructor(context: Context?, attrs: Attribute
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onChartMoved(movementX: Float, movementY: Float) {
|
// override fun onChartMoved(movementX: Float, movementY: Float) {
|
||||||
movementOffset = (movementX / 100).toInt()
|
// movementOffset = (movementX / 100).toInt()
|
||||||
refresh()
|
// refresh()
|
||||||
}
|
// }
|
||||||
|
|
||||||
override fun onZoomChanged(scale: Float) {
|
// override fun onZoomChanged(scale: Float) {
|
||||||
Log.d(TAG, "New Zoom: $scale")
|
// Log.d(TAG, "New Zoom: $scale")
|
||||||
zoom = (scale * 1.2).toFloat()
|
// zoom = (scale * 1.2).toFloat()
|
||||||
refresh()
|
// refresh()
|
||||||
}
|
// }
|
||||||
|
|
||||||
private fun getXOffset(): Int {
|
private fun getXOffset(): Int {
|
||||||
return min(max(0, xAxis.baseOffset + movementOffset), list.size - getDisplayedEntries())
|
return min(max(0, xAxis.baseOffset + movementOffset), list.size - getDisplayedEntries())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user