diff --git a/.github/screenshot.jpg b/.github/screenshot.jpg new file mode 100644 index 0000000..ed0e660 Binary files /dev/null and b/.github/screenshot.jpg differ diff --git a/.github/screenshot2.jpg b/.github/screenshot2.jpg new file mode 100644 index 0000000..9289457 Binary files /dev/null and b/.github/screenshot2.jpg differ diff --git a/.github/screenshot3.jpg b/.github/screenshot3.jpg new file mode 100644 index 0000000..e719c60 Binary files /dev/null and b/.github/screenshot3.jpg differ diff --git a/.github/usage-example.jpg b/.github/usage-example.jpg new file mode 100644 index 0000000..e43892a Binary files /dev/null and b/.github/usage-example.jpg differ diff --git a/README.md b/README.md index ece2f52..62cdde4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -# Crash Handler +

+ Dzeio Charts logo +

+ +# Dzeio Charts Highly customizable and easy to use Chart library for android @@ -10,6 +14,52 @@ Add to you dependencies (check the latest release for the version): - (Gradle Kotlin DSL) Add `implementation("com.dzeio:charts:1.0.0")` - (Gradle Groovy DSL) Add `implementation "com.dzeio:charts:1.0.0" ` +## Usage + +_note: full featured examples in the `sample` app_ + +Add this to your views + +```xml + +``` + + +```kotlin +val chart = binding.chart // get the chart from the view +// setup the Serie +val serie = LineSerie(chart) + +// give the serie its entries +serie.entries = // fill this with com.dzeio.charts.Entry +serie.entries = arrayListOf( + Entry( + 1, + 53f + ) +) + +// refresh the Chart +chart.refresh() +``` + +| Basic charts | Fully customized chart | Grouped/Stacked charts | +|:-----------------------------------------:|:-------------------------------------------:|:-------------------------------------------:| +| ![screenshot.jpg](.github/screenshot.jpg) | ![screenshot2.jpg](.github/screenshot2.jpg) | ![screenshot3.jpg](.github/screenshot3.jpg) | + +

+ Example Usage +

+

in a health oriented step counter with a daily goal

+

+ +

+ +_note: Every charts used above used a helper function to have Material 3 colors [See MainFragment.kt the materialTheme function](./sample/src/main/java/com/dzeio/chartstest/ui/MainFragment.kt)_ + ## Build - Install Android Studio diff --git a/library/src/main/java/com/dzeio/charts/ChartView.kt b/library/src/main/java/com/dzeio/charts/ChartView.kt index 4c7c1bf..910f657 100644 --- a/library/src/main/java/com/dzeio/charts/ChartView.kt +++ b/library/src/main/java/com/dzeio/charts/ChartView.kt @@ -2,15 +2,18 @@ package com.dzeio.charts import android.annotation.SuppressLint import android.content.Context +import android.content.res.Resources import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint +import android.graphics.Rect import android.graphics.RectF import android.util.AttributeSet 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.Animation import com.dzeio.charts.components.Annotation import com.dzeio.charts.components.ChartScroll import com.dzeio.charts.series.SerieInterface @@ -38,6 +41,39 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet override var padding: Float = 8f + private var runUpdates = true + + init { + viewTreeObserver.addOnScrollChangedListener { + val actualPosition = Rect() + val isGlobalVisible = getGlobalVisibleRect(actualPosition) + val screen = Rect( + 0, + 0, + Resources.getSystem().displayMetrics.widthPixels, + Resources.getSystem().displayMetrics.heightPixels + ) + val displayed = isShown && isGlobalVisible && Rect.intersects(actualPosition, screen) + + if (!displayed) { + if (!runUpdates) { + return@addOnScrollChangedListener + } + for (serie in series) { + serie.resetAnimation() + refresh() + runUpdates = false + } + } else if (!runUpdates) { + runUpdates = true + refresh() + } else if (annotator.entry != null && annotator.hideOnScroll) { + annotator.entry = null + refresh() + } + } + } + private val scroller = ChartScroll(this).apply { var lastMovementX = 0.0 var lastMovementY = 0f @@ -111,6 +147,9 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet } override fun refresh() { + if (!runUpdates) { + return + } // run Axis logics xAxis.refresh() yAxis.refresh() @@ -126,37 +165,46 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet // post(animator) } - override fun onDraw(canvas: Canvas) { + private var lastRun = runUpdates + override fun onDraw(canvas: Canvas) { // don't draw anything if everything is empty - if (series.isEmpty() || series.maxOf { it.entries.size } == 0) { + if (!runUpdates && lastRun == runUpdates && 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) + canvas.drawRect( + rect.apply { + set( + padding / 2, + padding / 2, + width.toFloat() - padding / 2, + height.toFloat() - padding / 2 + ) + }, + debugStrokePaint + ) } - var bottom = xAxis.getHeight() ?: 0f // right distance from the yAxis - val rightDistance = yAxis.onDraw(canvas, rect.apply { - set(padding, padding, width.toFloat() - padding, height.toFloat() - bottom - padding) - }) + val rightDistance = yAxis.onDraw( + canvas, + rect.apply { + set(padding, padding, width.toFloat() - padding, height.toFloat() - bottom - padding) + } + ) - bottom = xAxis.onDraw(canvas, rect.apply { - set(padding, 0f, width.toFloat() - rightDistance - padding, height.toFloat() - padding) - }) + bottom = xAxis.onDraw( + canvas, + rect.apply { + set(padding, 0f, width.toFloat() - rightDistance - padding, height.toFloat() - padding) + } + ) // chart draw rectangle seriesRect.apply { @@ -187,7 +235,9 @@ class ChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet annotator.onDraw(canvas, seriesRect) - postDelayed({ this.invalidate() }, animator.getDelay().toLong()) + if (needRedraw && runUpdates) { + postDelayed({ this.invalidate() }, animator.getDelay().toLong()) + } super.onDraw(canvas) } diff --git a/library/src/main/java/com/dzeio/charts/ChartViewInterface.kt b/library/src/main/java/com/dzeio/charts/ChartViewInterface.kt index 208c64d..16ec3d7 100644 --- a/library/src/main/java/com/dzeio/charts/ChartViewInterface.kt +++ b/library/src/main/java/com/dzeio/charts/ChartViewInterface.kt @@ -2,6 +2,7 @@ package com.dzeio.charts import com.dzeio.charts.axis.XAxisInterface import com.dzeio.charts.axis.YAxisInterface +import com.dzeio.charts.components.Animation import com.dzeio.charts.components.Annotation import com.dzeio.charts.series.SerieInterface diff --git a/library/src/main/java/com/dzeio/charts/Animation.kt b/library/src/main/java/com/dzeio/charts/components/Animation.kt similarity index 98% rename from library/src/main/java/com/dzeio/charts/Animation.kt rename to library/src/main/java/com/dzeio/charts/components/Animation.kt index f318f17..d8b725c 100644 --- a/library/src/main/java/com/dzeio/charts/Animation.kt +++ b/library/src/main/java/com/dzeio/charts/components/Animation.kt @@ -1,4 +1,4 @@ -package com.dzeio.charts +package com.dzeio.charts.components import kotlin.math.abs diff --git a/library/src/main/java/com/dzeio/charts/series/BarSerie.kt b/library/src/main/java/com/dzeio/charts/series/BarSerie.kt index bdb9612..66dfe21 100644 --- a/library/src/main/java/com/dzeio/charts/series/BarSerie.kt +++ b/library/src/main/java/com/dzeio/charts/series/BarSerie.kt @@ -175,4 +175,8 @@ class BarSerie( override fun refresh() { // TODO("Not yet implemented") } + + override fun resetAnimation() { + entriesCurrentY.clear() + } } diff --git a/library/src/main/java/com/dzeio/charts/series/LineSerie.kt b/library/src/main/java/com/dzeio/charts/series/LineSerie.kt index ebdf248..adb5cbd 100644 --- a/library/src/main/java/com/dzeio/charts/series/LineSerie.kt +++ b/library/src/main/java/com/dzeio/charts/series/LineSerie.kt @@ -177,4 +177,8 @@ class LineSerie( override fun refresh() { // TODO("Not yet implemented") } + + override fun resetAnimation() { + entriesCurrentY.clear() + } } diff --git a/library/src/main/java/com/dzeio/charts/series/SerieInterface.kt b/library/src/main/java/com/dzeio/charts/series/SerieInterface.kt index c78b63f..1d79691 100644 --- a/library/src/main/java/com/dzeio/charts/series/SerieInterface.kt +++ b/library/src/main/java/com/dzeio/charts/series/SerieInterface.kt @@ -45,4 +45,6 @@ sealed interface SerieInterface { * this is where the pre-logic is handled to make [onDraw] quicker */ fun refresh() + + fun resetAnimation() } diff --git a/sample/src/main/ic_launcher-playstore.png b/sample/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..5d4beb0 Binary files /dev/null and b/sample/src/main/ic_launcher-playstore.png differ diff --git a/sample/src/main/res/drawable-v24/ic_launcher_foreground.xml b/sample/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d1..0000000 --- a/sample/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/sample/src/main/res/drawable/ic_launcher_background.xml b/sample/src/main/res/drawable/ic_launcher_background.xml index 07d5da9..6b8b75b 100644 --- a/sample/src/main/res/drawable/ic_launcher_background.xml +++ b/sample/src/main/res/drawable/ic_launcher_background.xml @@ -2,169 +2,10 @@ + android:viewportWidth="512" + android:viewportHeight="512" + android:tint="#FFFFFF"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:pathData="M0,0h512v512h-512z" + android:fillColor="#FF000000"/> diff --git a/sample/src/main/res/drawable/ic_launcher_foreground.xml b/sample/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2c3c2cf --- /dev/null +++ b/sample/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index eca70cf..93542a7 100644 --- a/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/sample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,6 @@ - - - \ No newline at end of file + + + + diff --git a/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..93542a7 --- /dev/null +++ b/sample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher.png b/sample/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..9a4bd2d Binary files /dev/null and b/sample/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher.webp b/sample/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78..0000000 Binary files a/sample/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ diff --git a/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..16a90aa Binary files /dev/null and b/sample/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher.png b/sample/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..e8e22ca Binary files /dev/null and b/sample/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher.webp b/sample/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d6..0000000 Binary files a/sample/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..0ffa307 Binary files /dev/null and b/sample/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..182ee33 Binary files /dev/null and b/sample/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher.webp b/sample/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 948a307..0000000 Binary files a/sample/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ diff --git a/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..17b7af2 Binary files /dev/null and b/sample/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..c2affae Binary files /dev/null and b/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/sample/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 28d4b77..0000000 Binary files a/sample/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..df3d2ab Binary files /dev/null and b/sample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..527d57e Binary files /dev/null and b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index aa7d642..0000000 Binary files a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..25840cb Binary files /dev/null and b/sample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/sample/src/main/res/values/ic_launcher_background.xml b/sample/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/sample/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file