From f6afb2a8cb3d4496ba04371d5519f433adb330a2 Mon Sep 17 00:00:00 2001 From: johan12345 Date: Tue, 20 Sep 2022 21:12:52 +0200 Subject: [PATCH] Add some labels to BarGraphView --- .../net/vonforst/evmap/ui/BarGraphView.kt | 97 +++++++++++++++++-- app/src/main/res/layout/detail_view.xml | 20 +++- app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 4 files changed, 108 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/net/vonforst/evmap/ui/BarGraphView.kt b/app/src/main/java/net/vonforst/evmap/ui/BarGraphView.kt index e5e3fbfb..453fccd8 100644 --- a/app/src/main/java/net/vonforst/evmap/ui/BarGraphView.kt +++ b/app/src/main/java/net/vonforst/evmap/ui/BarGraphView.kt @@ -2,19 +2,28 @@ package net.vonforst.evmap.ui import android.content.Context import android.graphics.Canvas +import android.graphics.DashPathEffect +import android.graphics.Paint import android.graphics.Rect import android.util.AttributeSet import android.view.View import androidx.appcompat.content.res.AppCompatResources import net.vonforst.evmap.R +import java.time.ZoneId import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.time.format.FormatStyle import kotlin.math.roundToInt class BarGraphView(context: Context, attrs: AttributeSet) : View(context, attrs) { var zeroHeight = 4 * context.resources.displayMetrics.density - var barWidth = 16 * context.resources.displayMetrics.density - var barMargin = 2 * context.resources.displayMetrics.density + var barWidth = (16 * context.resources.displayMetrics.density).roundToInt() + var barMargin = (2 * context.resources.displayMetrics.density).roundToInt() + var legendWidth = 12 * context.resources.displayMetrics.density + var legendLineLength = 4 * context.resources.displayMetrics.density + var legendLineWidth = 1 * context.resources.displayMetrics.density + var dashLength = 4 * context.resources.displayMetrics.density var barDrawableUnavailable = AppCompatResources.getDrawable(context, R.drawable.bar_graph_unavailable)!! @@ -26,35 +35,107 @@ class BarGraphView(context: Context, attrs: AttributeSet) : View(context, attrs) field = value invalidate() } + var maxValue: Int? = null + set(value) { + field = value + invalidate() + } var activeAlpha = 0.87f var inactiveAlpha = 0.60f + private val legendPaint = Paint().apply { + val ta = context.theme.obtainStyledAttributes(intArrayOf(R.attr.colorControlNormal)) + color = ta.getColor(0, 0) + strokeWidth = legendLineWidth + textSize = legendWidth - legendLineLength + } + private val legendDashedPaint = Paint().apply { + set(legendPaint) + alpha = (inactiveAlpha * 255).roundToInt() + style = Paint.Style.STROKE + pathEffect = DashPathEffect(floatArrayOf(dashLength, dashLength), 0f) + } + private lateinit var graphBounds: Rect override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { - graphBounds = Rect(paddingLeft, paddingTop, w - paddingRight, h - paddingBottom) + val bottom = (paddingBottom + legendWidth).roundToInt() + val left = (paddingLeft + legendWidth).roundToInt() + val right = (paddingRight + legendWidth).roundToInt() + val top = (paddingTop + (legendWidth - legendLineLength) / 3 * 2).roundToInt() + graphBounds = Rect(left, top, w - right, h - bottom) } + private val timeFormat = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT) + override fun onDraw(canvas: Canvas) { - val data = data ?: return - val maxValue = data.maxOf { it.value } + val data = data?.toSortedMap() ?: return + val maxValue = maxValue ?: data.maxOf { it.value } canvas.apply { - data.toSortedMap().entries.forEachIndexed { i, (t, v) -> + drawLine( + graphBounds.left.toFloat(), + graphBounds.top.toFloat(), + graphBounds.right.toFloat(), + graphBounds.top.toFloat(), + legendDashedPaint + ) + + legendPaint.textAlign = Paint.Align.CENTER + data.entries.forEachIndexed { i, (t, v) -> val drawable = if (v > 0) barDrawableAvailable else barDrawableUnavailable val height = zeroHeight + (graphBounds.height() - zeroHeight) * v.toFloat() / maxValue + val left = graphBounds.left + (barWidth + barMargin) * i + + if (left + barWidth > graphBounds.right) return@forEachIndexed + drawable.setBounds( - graphBounds.left + ((barWidth + barMargin) * i).roundToInt(), + left, graphBounds.bottom - height.roundToInt(), - graphBounds.left + ((barWidth + barMargin) * i + barWidth).roundToInt(), + left + barWidth, graphBounds.bottom ) drawable.alpha = (inactiveAlpha * 255).roundToInt() drawable.draw(canvas) + + if (t.minute == 0) { + val center = left.toFloat() + barWidth / 2 + drawLine( + center, graphBounds.bottom.toFloat(), + center, graphBounds.bottom + legendLineLength, legendPaint + ) + drawText( + t.withZoneSameInstant(ZoneId.systemDefault()).format(timeFormat), + center, graphBounds.bottom + legendWidth, legendPaint + ) + } } + + drawLine( + graphBounds.left.toFloat(), + graphBounds.bottom.toFloat(), + graphBounds.right.toFloat(), + graphBounds.bottom.toFloat(), + legendPaint + ) + drawLine( + graphBounds.left.toFloat(), + graphBounds.bottom.toFloat(), + graphBounds.right.toFloat(), + graphBounds.bottom.toFloat(), + legendPaint + ) + + legendPaint.textAlign = Paint.Align.LEFT + drawText( + maxValue.toString(), + graphBounds.right.toFloat() + legendLineLength, + graphBounds.top + (legendWidth - legendLineLength) / 3, + legendPaint + ) } } } \ No newline at end of file diff --git a/app/src/main/res/layout/detail_view.xml b/app/src/main/res/layout/detail_view.xml index a88c71aa..dd3fcddb 100644 --- a/app/src/main/res/layout/detail_view.xml +++ b/app/src/main/res/layout/detail_view.xml @@ -335,16 +335,30 @@ app:layout_constraintStart_toStartOf="@+id/guideline" app:layout_constraintTop_toBottomOf="@+id/prediction" /> + + OpenStreetMap (Mapbox) Mitwirkende Dank an alle Mitwirkenden für ihre Beiträge von Code und Übersetzungen für EVMap: + Verfügbarkeitsprognose \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8d2e24ac..d190c2f0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -269,4 +269,5 @@ OpenStreetMap (Mapbox) Contributors Thanks to all contributors for their coding and translation contributions to EVMap: + Availability prediction