fix(map): chart fill padding and dropdown selected border
- AirMQChart: add bottom padding so fill extends below line and thick line stays in bounds - DeviceSensorDropdown: show border on selected item when dropdown is opened Made-with: Cursor
This commit is contained in:
@@ -179,15 +179,17 @@ fun AirMQChart(
|
||||
val innerLeft = with(density) { ChartPaddingLeftDp.toPx() }
|
||||
val innerRight = w - with(density) { ChartPaddingRightDp.toPx() }
|
||||
val innerTop = with(density) { ChartPaddingTopDp.toPx() }
|
||||
val bottomPaddingPx = with(density) { 12.dp.toPx() }
|
||||
val bottomMarginPx = with(density) { 16.dp.toPx() }
|
||||
val fakePieceTop = h - bottomMarginPx - 1f
|
||||
val innerBottomLegacy = h - with(density) { ChartPaddingBottomDp.toPx() }
|
||||
val fillBottom = if (config.roundCorners) fakePieceTop else innerBottomLegacy + bottomMarginPx
|
||||
// fillBottom = where the fill extends to (space below line is filled with same color)
|
||||
// chartBottom = where the line's lowest point plots (keeps thick line inside bounds, padding above fillBottom)
|
||||
val fillBottom = if (config.roundCorners) h - bottomMarginPx - 1f else h
|
||||
val chartBottom = fillBottom - bottomPaddingPx
|
||||
val chartWidth = innerRight - innerLeft
|
||||
val chartHeight = fillBottom - innerTop
|
||||
val chartHeight = chartBottom - innerTop
|
||||
|
||||
fun toX(ts: Long) = innerLeft + ((ts - xMin) / rangeX.toFloat()) * chartWidth
|
||||
fun toY(v: Float) = fillBottom - ((v - yMin) / rangeY) * chartHeight
|
||||
fun toY(v: Float) = chartBottom - ((v - yMin) / rangeY) * chartHeight
|
||||
|
||||
drawChartBackground(
|
||||
left = innerLeft,
|
||||
@@ -244,7 +246,7 @@ fun AirMQChart(
|
||||
innerLeft = innerLeft,
|
||||
innerRight = innerRight,
|
||||
innerTop = innerTop,
|
||||
fillBottom = fillBottom,
|
||||
chartBottom = chartBottom,
|
||||
config = config,
|
||||
unit = unit,
|
||||
textMeasurer = textMeasurer
|
||||
@@ -264,7 +266,7 @@ fun AirMQChart(
|
||||
innerLeft = innerLeft,
|
||||
innerRight = innerRight,
|
||||
innerTop = innerTop,
|
||||
fillBottom = fillBottom,
|
||||
chartBottom = chartBottom,
|
||||
textMeasurer = textMeasurer
|
||||
)
|
||||
}
|
||||
@@ -520,7 +522,7 @@ private fun DrawScope.drawLabels(
|
||||
innerLeft: Float,
|
||||
innerRight: Float,
|
||||
innerTop: Float,
|
||||
fillBottom: Float,
|
||||
chartBottom: Float,
|
||||
config: ChartConfig,
|
||||
unit: String,
|
||||
textMeasurer: androidx.compose.ui.text.TextMeasurer
|
||||
@@ -533,15 +535,15 @@ private fun DrawScope.drawLabels(
|
||||
val pad = with(density) { 8.dp.toPx() }
|
||||
val textLayout = textMeasurer.measure("0", TextStyle(fontSize = LabelTextSizeSp.sp))
|
||||
val baselineOffset = textLayout.size.height * 0.75f
|
||||
val chartHeight = fillBottom - innerTop
|
||||
val chartHeight = chartBottom - innerTop
|
||||
val midY = (maxY + minY) / 2f
|
||||
val midText = formatRounded(midY, rangeY)
|
||||
val midYpos = innerTop + chartHeight / 2f + baselineOffset
|
||||
val bottomBaseline = fillBottom + baselineOffset
|
||||
val bottomBaseline = chartBottom + baselineOffset
|
||||
drawTextLabelRightAligned(maxText, innerLeft - pad, innerTop + baselineOffset, labelColor, textMeasurer)
|
||||
drawTextLabelRightAligned(midText, innerLeft - pad, midYpos, labelColor, textMeasurer)
|
||||
drawTextLabelRightAligned(minText, innerLeft - pad, bottomBaseline, labelColor, textMeasurer)
|
||||
val lastYpos = fillBottom - ((lastY - minY) / rangeY) * chartHeight
|
||||
val lastYpos = chartBottom - ((lastY - minY) / rangeY) * chartHeight
|
||||
val lastTextLayout = textMeasurer.measure(lastText, TextStyle(fontSize = LabelTextSizeSp.sp))
|
||||
val lastBaseline = lastYpos - lastTextLayout.size.height / 3f
|
||||
drawTextLabel(lastText, innerRight + pad, lastBaseline, labelColor, textMeasurer)
|
||||
@@ -592,11 +594,11 @@ private fun DrawScope.drawMarker(
|
||||
innerLeft: Float,
|
||||
innerRight: Float,
|
||||
innerTop: Float,
|
||||
fillBottom: Float,
|
||||
chartBottom: Float,
|
||||
textMeasurer: androidx.compose.ui.text.TextMeasurer
|
||||
) {
|
||||
drawLine(config.lineColor, Offset(innerLeft, y), Offset(innerRight, y), strokeWidth = 1f)
|
||||
drawLine(config.lineColor, Offset(x, innerTop - 16), Offset(x, fillBottom + 16), strokeWidth = 1f)
|
||||
drawLine(config.lineColor, Offset(x, innerTop - 16), Offset(x, chartBottom + 16), strokeWidth = 1f)
|
||||
drawCircle(config.lineColor, radius = MarkerRadiusPx, center = Offset(x, y))
|
||||
|
||||
val valueStr = "${formatRounded(point.value, rangeY)} $unit".trim()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.db3.airmq.features.map
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -27,6 +28,7 @@ import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -576,8 +578,8 @@ private fun DeviceSensorDropdown(
|
||||
) {
|
||||
AnimatedVisibility(
|
||||
visible = isExpanded,
|
||||
enter = expandVertically(),
|
||||
exit = shrinkVertically()
|
||||
enter = expandVertically(animationSpec = tween(durationMillis = 150)),
|
||||
exit = shrinkVertically(animationSpec = tween(durationMillis = 150))
|
||||
) {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
@@ -593,6 +595,7 @@ private fun DeviceSensorDropdown(
|
||||
DeviceSensorDropdownOption(
|
||||
sensorType = sensorType,
|
||||
selected = selectedSensor == sensorType,
|
||||
showSelectedBorder = isExpanded && selectedSensor == sensorType,
|
||||
onClick = {
|
||||
onSelected(sensorType)
|
||||
isExpanded = false
|
||||
@@ -664,12 +667,17 @@ private fun sensorLabelRes(sensorType: DeviceSensorType): Int = when (sensorType
|
||||
private fun DeviceSensorDropdownOption(
|
||||
sensorType: DeviceSensorType,
|
||||
selected: Boolean,
|
||||
showSelectedBorder: Boolean,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val textColor = if (selected) Color(0xFF1C1C1C) else Color(0xFF616161)
|
||||
val borderModifier = if (showSelectedBorder) {
|
||||
Modifier.border(1.dp, Color(0x61000000), RoundedCornerShape(8.dp))
|
||||
} else Modifier
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.then(borderModifier)
|
||||
.clickable(onClick = onClick)
|
||||
.padding(horizontal = 16.dp, vertical = 10.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
|
||||
Reference in New Issue
Block a user