Skip to content

Instantly share code, notes, and snippets.

@decodeandroid
Created May 30, 2024 12:00
Show Gist options
  • Select an option

  • Save decodeandroid/749615c30543bbe7eee46d77f2bd4163 to your computer and use it in GitHub Desktop.

Select an option

Save decodeandroid/749615c30543bbe7eee46d77f2bd4163 to your computer and use it in GitHub Desktop.
Bar Chart Jetpack Compose Canvas
@Composable
fun BarChart() {
val chartData = listOf(
Pair("I", 90),
Pair("II", 110),
Pair("III", 70),
Pair("IV", 205),
Pair("V", 150),
Pair("VI", 175)
)
val spacingFromLeft = 100f
val spacingFromBottom = 40f
val upperValue = remember { (chartData.maxOfOrNull { it.second }?.plus(1)) ?: 0 }
val lowerValue = remember { (chartData.minOfOrNull { it.second }?.toInt() ?: 0) }
val density = LocalDensity.current
//paint for the text shown in data values
val textPaint = remember(density) {
Paint().apply {
color = android.graphics.Color.BLACK
textAlign = Paint.Align.CENTER
textSize = density.run { 12.sp.toPx() }
}
}
androidx.compose.foundation.Canvas(
modifier = Modifier
.fillMaxWidth()
.height(300.dp)
.background(Color.White)
.padding(16.dp)
) {
val canvasHeight = size.height
val canvasWidth = size.width
val spacePerData = (canvasWidth - spacingFromLeft) / chartData.size
//loop through each index by step of 1
//data shown horizontally
(chartData.indices step 1).forEach { i ->
val text = chartData[i].first
drawContext.canvas.nativeCanvas.apply {
drawText(
text,
spacingFromLeft + 30f + i * spacePerData,
canvasHeight,
textPaint
)
}
}
val valuesToShow = 5f //we will show 5 data values on vertical line
val eachStep = (upperValue - lowerValue) / valuesToShow
//data shown vertically
(0..4).forEach { i ->
drawContext.canvas.nativeCanvas.apply {
drawText(
round(lowerValue + eachStep * i).toString(),
20f,
canvasHeight - 30f - i * canvasHeight / 5f,
textPaint
)
}
//draw horizontal line at each value
drawLine(
start = Offset(
spacingFromLeft - 20f,
canvasHeight - spacingFromBottom - i * canvasHeight / 5f
),
end = Offset(
spacingFromLeft,
canvasHeight - spacingFromBottom - i * canvasHeight / 5f
),
color = Color.Black,
strokeWidth = 3f
)
}
//Vertical line
drawLine(
start = Offset(spacingFromLeft, canvasHeight - spacingFromBottom),
end = Offset(spacingFromLeft, 0f),
color = Color.Black,
strokeWidth = 3f
)
//Horizontal line
drawLine(
start = Offset(spacingFromLeft, canvasHeight - spacingFromBottom),
end = Offset(canvasWidth - 40f, canvasHeight - spacingFromBottom),
color = Color.Black,
strokeWidth = 3f
)
//draw bars
chartData.forEachIndexed { index, chartPair ->
//draw text at top of each bar
drawContext.canvas.nativeCanvas.apply {
drawText(
chartPair.second.toString(),
spacingFromLeft + 40f + index * spacePerData,
(upperValue - chartPair.second.toFloat()) / upperValue * canvasHeight - 10f,
textPaint
)
}
//draw Bar for each value
drawRoundRect(
color = Color.Magenta,
topLeft = Offset(
spacingFromLeft + 10f + index * spacePerData,
(upperValue - chartPair.second.toFloat()) / upperValue * canvasHeight
),
size = Size(
55f,
(chartPair.second.toFloat() / upperValue) * canvasHeight - spacingFromBottom
),
cornerRadius = CornerRadius(10f, 10f)
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment