Skip to content

Instantly share code, notes, and snippets.

@ardakazanci
Created April 24, 2024 15:49
Show Gist options
  • Save ardakazanci/5ec373ee38e00af9f04889a2da046d45 to your computer and use it in GitHub Desktop.
Save ardakazanci/5ec373ee38e00af9f04889a2da046d45 to your computer and use it in GitHub Desktop.
Bar with JetpackCompose
data class BarDataM(val value: Float, val label: String)
@Composable
fun BarChartComponent(
bars: List<BarDataM>,
barWidth: Dp,
spaceBetweenBars: Dp,
animateChart: Boolean
) {
var selectedBar by remember { mutableIntStateOf(-1) }
var dropRate by remember { mutableFloatStateOf(0f) }
val animatedBarHeights = bars.map { bar ->
animateFloatAsState(
targetValue = if (animateChart) bar.value else 0f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
)
)
}
Column {
Canvas(
modifier = Modifier
.height(250.dp)
.fillMaxWidth()
) {
val spacingPx = spaceBetweenBars.toPx()
val barWidthPx = barWidth.toPx()
val path = Path()
bars.forEachIndexed { index, bar ->
val x = index * (barWidthPx + spacingPx) + spacingPx / 2
val barTopY = size.height - (animatedBarHeights[index].value * size.height)
val color = if (index == selectedBar) Color(0xFF51E470) else Color(0XFFE8EAEE)
drawRoundRect(
color = color,
topLeft = Offset(x + 50f, barTopY),
size = Size(barWidthPx, animatedBarHeights[index].value * size.height),
cornerRadius = CornerRadius(x = 15f, y = 15f)
)
if (index == 0) {
path.moveTo(x + 50f + barWidthPx / 2, barTopY)
} else {
path.lineTo(x + 50f + barWidthPx / 2, barTopY)
}
if (index == selectedBar) {
val dropText = "$dropRate%"
val textPaint = Paint().apply {
textSize = 10.sp.toPx()
setColor(android.graphics.Color.RED)
textAlign = android.graphics.Paint.Align.CENTER
}
drawContext.canvas.nativeCanvas.drawText(
dropText,
x + 50f + barWidthPx / 2,
barTopY - 10.dp.toPx(),
textPaint
)
}
}
drawPath(
path = path,
brush = Brush.linearGradient(listOf(Color.Black, Color.Black.copy(alpha = 0.5f))),
style = Stroke(width = 4f)
)
}
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(
spaceBetweenBars,
Alignment.CenterHorizontally
)
) {
bars.forEachIndexed { index, bar ->
Box(modifier = Modifier
.width(barWidth)
.noRippleClickable {
selectedBar = index
dropRate = Random.nextFloat() * 10
}
) {
Spacer(modifier = Modifier.height(5.dp))
Text(
color = Color.Black.copy(alpha = 0.5f),
text = bar.label,
fontSize = 12.sp,
modifier = Modifier.align(Alignment.Center)
)
}
}
}
}
}
@Composable
fun Bar() {
val bars = listOf(
BarDataM(0.7f, "Sun"),
BarDataM(0.4f, "Mon"),
BarDataM(0.5f, "Tue"),
BarDataM(0.6f, "Wed"),
BarDataM(0.3f, "Today")
)
var animateChart by remember { mutableStateOf(false) }
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Button(onClick = { animateChart = !animateChart }) {
Text("Toggle Animation")
}
BarChartComponent(
bars = bars,
barWidth = 50.dp,
spaceBetweenBars = 20.dp,
animateChart = animateChart
)
}
}
fun Modifier.noRippleClickable(onClick: () -> Unit): Modifier = composed {
this.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }) {
onClick()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment