Created
September 29, 2024 16:44
-
-
Save logickoder/922b2d0e942f9e5731ef56be0c3cb598 to your computer and use it in GitHub Desktop.
Compose Hour Bar Chart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package dev.logickoder.compose.chart | |
import androidx.compose.foundation.Canvas | |
import androidx.compose.foundation.background | |
import androidx.compose.foundation.layout.Arrangement | |
import androidx.compose.foundation.layout.Box | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.Row | |
import androidx.compose.foundation.layout.fillMaxWidth | |
import androidx.compose.foundation.layout.height | |
import androidx.compose.foundation.layout.size | |
import androidx.compose.foundation.shape.CircleShape | |
import androidx.compose.material3.Text | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.remember | |
import androidx.compose.ui.Alignment | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.geometry.Offset | |
import androidx.compose.ui.geometry.Size | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.tooling.preview.Preview | |
import androidx.compose.ui.unit.Dp | |
import androidx.compose.ui.unit.dp | |
import androidx.compose.ui.unit.sp | |
@Composable | |
fun ChartView( | |
barHeight: Dp, | |
modifier: Modifier = Modifier, | |
) { | |
val list = remember { | |
buildList { | |
add(OneHour) | |
repeat(5) { | |
add((0..TwentyFourHours).random().toLong()) | |
} | |
add(TwentyFourHours) | |
} | |
} | |
val blockWidthDp = 19.dp | |
val textWidth = 30.dp | |
Column( | |
modifier = modifier, | |
verticalArrangement = Arrangement.spacedBy(19.dp), | |
content = { | |
Canvas( | |
modifier = Modifier | |
.height(barHeight) | |
.fillMaxWidth() | |
.background(Color.Green), | |
onDraw = { | |
// Draw the horizontal lines | |
val lines = 4 | |
var space = size.height / (lines - 1) | |
var startY = 0f | |
repeat(lines) { | |
drawLine( | |
color = Color.Yellow, | |
start = Offset(0f, startY), | |
end = Offset(size.width, startY), | |
strokeWidth = 1.dp.toPx() | |
) | |
startY += space | |
} | |
// Draw the bars | |
val blockWidth = blockWidthDp.toPx() | |
val minWidth = minOf(blockWidthDp, textWidth).toPx() | |
val maxWidth = maxOf(blockWidthDp, textWidth).toPx() | |
space = (size.width - (maxWidth * list.size)) / (list.size - 1) | |
var startX = 0f | |
for (i in list.indices) { | |
val hour = list[i] | |
val height = (hour / TwentyFourHours.toFloat()) * size.height | |
val trimWidth = maxWidth - minWidth | |
drawRect( | |
color = Color.Red, | |
topLeft = Offset(startX + trimWidth / 2, size.height - height), | |
size = Size(blockWidth, height) | |
) | |
startX += maxWidth + space | |
} | |
} | |
) | |
Row( | |
modifier = Modifier.fillMaxWidth(), | |
horizontalArrangement = Arrangement.SpaceBetween, | |
content = { | |
Days.forEach { day -> | |
Box( | |
modifier = Modifier | |
.size(textWidth) | |
.background(Color.Yellow, shape = CircleShape), | |
contentAlignment = Alignment.Center, | |
content = { | |
Text(text = day, fontSize = 15.sp, color = Color.Black) | |
} | |
) | |
} | |
} | |
) | |
} | |
) | |
} | |
private const val OneHour = 1_000L * 60 * 60 // 1hr in millis | |
private const val TwentyFourHours = OneHour * 24 | |
private val Days = listOf("M", "T", "W", "T", "F", "S", "S") | |
@Preview(showBackground = true) | |
@Composable | |
private fun ChartViewPreview() { | |
ChartView(200.dp) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Preview