Build an Animated Dashboard with Spring Physics | Kotlin Desktop #1
Video: Build an Animated Dashboard with Spring Physics | Kotlin Desktop #1 by Taught by Celeste AI - AI Coding Coach
Watch full page →Build an Animated Dashboard with Spring Physics in Kotlin Desktop
Learn how to create a dynamic and visually appealing dashboard using Kotlin Compose Desktop by leveraging spring physics for natural animations. This example demonstrates animating values with animateXAsState, smooth color transitions, enter/exit animations with AnimatedVisibility, and continuous shimmer effects using rememberInfiniteTransition.
Code
import androidx.compose.animation.*
import androidx.compose.animation.core.*
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@Composable
fun AnimatedDashboard() {
var selectedTab by remember { mutableStateOf(0) }
// Animate tab content crossfade
Crossfade(targetState = selectedTab) { tab ->
when (tab) {
0 -> StatCard(value = 75, label = "CPU Usage", color = Color(0xFF4CAF50))
1 -> StatCard(value = 40, label = "Memory", color = Color(0xFF2196F3))
}
}
Spacer(Modifier.height(16.dp))
// Tab buttons
Row {
listOf("CPU", "Memory").forEachIndexed { index, title ->
Button(onClick = { selectedTab = index }, Modifier.padding(4.dp)) {
Text(title)
}
}
}
}
@Composable
fun StatCard(value: Int, label: String, color: Color) {
// Animate progress value with spring physics for bouncy effect
val animatedValue by animateIntAsState(
targetValue = value,
animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy, stiffness = Spring.StiffnessLow)
)
// Animate color transition smoothly
val animatedColor by animateColorAsState(targetValue = color)
// Infinite shimmer effect for pulse
val infiniteTransition = rememberInfiniteTransition()
val pulseAlpha by infiniteTransition.animateFloat(
initialValue = 0.3f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(1000, easing = FastOutSlowInEasing),
repeatMode = RepeatMode.Reverse
)
)
Card(
shape = RoundedCornerShape(12.dp),
modifier = Modifier.size(150.dp, 150.dp),
colors = CardDefaults.cardColors(containerColor = animatedColor.copy(alpha = pulseAlpha))
) {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
// Draw progress ring
Canvas(Modifier.size(100.dp)) {
val sweepAngle = (animatedValue / 100f) * 360f
drawArc(
color = animatedColor,
startAngle = -90f,
sweepAngle = sweepAngle,
useCenter = false,
style = androidx.compose.ui.graphics.drawscope.Stroke(width = 12f)
)
}
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text("$animatedValue%", style = MaterialTheme.typography.headlineMedium, color = Color.White)
Text(label, style = MaterialTheme.typography.bodyMedium, color = Color.White.copy(alpha = 0.7f))
}
}
}
}
Key Points
- Use
animateIntAsStatewith spring physics for natural, bouncy value animations. animateColorAsStateenables smooth color transitions for UI elements.Crossfadeprovides seamless content switching between different dashboard tabs.rememberInfiniteTransitioncreates continuous shimmer or pulsing animation effects.Canvas.drawArcis useful for drawing animated progress rings representing dynamic data.