What might be desirable is to have the lowest value to have at least a height of the corresponding bar width, for instance. At the same time I don't know how to improve the autoScaleRange API myself, so unfortunately I can't give any suggestions.
data class Dto(
val value: Float,
val label: String
)
val someDtos = listOf(
Dto(value=91.59999F, label="F"),
Dto(value=91.89999F, label="S"),
Dto(value=91.299995F,label="S"),
Dto(value=91.0F,label="M"),
Dto(value=91.8F,label="T"),
Dto(value=92.0F,label="W"),
Dto(value=91.8F,label="T")
)
@OptIn(ExperimentalKoalaPlotApi::class)
@Composable
fun BarChartRenderer(
dtos: List<Dto> = someDtos,
modifier: Modifier = Modifier
) {
if (dtos.isEmpty()) return
if (dtos.all { it.value == 0F }) return
val weekdayIndexCategories = dtos.weekdayIndexCategories()
val dtoCountWeekday = dtos.dtoValueWeekday()
val dtoColor = Color.Blue
XYGraph(
xAxisModel = remember(weekdayIndexCategories) {
CategoryAxisModel(
categories = weekdayIndexCategories,
categoryAxisOffset = CategoryAxisOffset.Custom(offset = 0.25F)
)
},
yAxisModel = rememberFloatLinearAxisModel(
range = dtoCountWeekday.autoScaleRange(),
minorTickCount = 0
),
modifier = modifier
.height(barChartHeight)
.padding(top = 4.dp)
.fillMaxWidth(),
xAxisContent = AxisContent(
style = rememberAxisStyle(
color = Color.LightGray
),
labels = {
dtos
.getOrNull(it)
?.let { dto ->
Text(
text = dto.label,
color = MaterialTheme.colorScheme.onBackground,
style = MaterialTheme.typography.bodySmall,
modifier = Modifier.padding(top = 4.dp)
)
}
},
title = { }
),
yAxisContent = AxisContent(
style = rememberAxisStyle(
color = Color.LightGray
),
labels = { dtoValue ->
Text(
text = dtoValue.roundToInt().toString(),
color = MaterialTheme.colorScheme.onBackground,
style = MaterialTheme.typography.bodySmall,
modifier = Modifier.padding(end = 4.dp)
)
},
title = { }
),
gridStyle = rememberGridStyle(
horizontalMajorStyle = null,
horizontalMinorStyle = null,
verticalMajorStyle = null,
verticalMinorStyle = null
)
) {
VerticalBarPlot(
xData = weekdayIndexCategories,
yData = dtoCountWeekday,
bar = verticalPlanoConvexBar(dtoColor),
barWidth = 0.5F
)
}
}
private val barChartHeight = 200.dp
private fun List<Dto>.weekdayIndexCategories(): List<Int> =
indices.toList()
private fun List<Dto>.dtoValueWeekday(): List<Float> =
map { it.value }
The autoScaleRange API unfortunately leads to misleading bar plot rendering. As seen in the example code, none of the values is
0Fand still the middle bar is not rendered since the range seems to start from the lowest value of the set.What might be desirable is to have the lowest value to have at least a height of the corresponding bar width, for instance. At the same time I don't know how to improve the
autoScaleRangeAPI myself, so unfortunately I can't give any suggestions.