Skip to content

Instantly share code, notes, and snippets.

// Rotation of the gradient
rotate(animationAngle / 2, pivot = center) {
drawRect(
Brush.linearGradient(
colors = listOf(
Color.Red, Color.Yellow, Color.Green, Color.Blue, Color.Magenta
)
),
blendMode = BlendMode.DstAtop
)
...
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
val size = 300.dp
var progress by remember { mutableStateOf(0f) }
var animationAngle by remember { mutableStateOf(0f) }
Box(
modifier = Modifier
Spacer(
...
.drawBehind {
...
hours.forEach {
if (!dotsVisibility[it]) return@forEach
val degree = it * 30f
rotate(degree) {
// Based on the hour value, the travel distance will be longer.
val positionY = halfStroke +
// Assume that duration is 1/12th of the whole duration, which equals to the length of 2 hours. It can be longer or shorter if necessary
val disassembleDuration = duration / 12
LaunchedEffect(currentHourFlow) {
currentHourFlow.collectLatest {
// launch each animation asynchronously
launch {
if (currentHour < 12) {
disassembleAnimations[currentHour].snapTo(0f)
// Set a tween spec with LinearOutSlowIn easing
// Remove derivedStateOf
var currentHour by remember { mutableStateOf(0) }
LaunchedEffect(animationAngle) {
// Add hour calculation inside of a launchEffect
val newCurrentHour = animationAngle.toInt() / 30
if (newCurrentHour != currentHour) {
currentHour = newCurrentHour
// Sending currentHour through channel
Spacer(
...
.drawBehind {
// A rotation section of a clock hand
rotate(animationAngle, pivot = center){
// Drawing a clock hand itself
drawLine(
color = Color.White,
start = center,
// Start calculation each time the animationAngle changes.
val assembleValue = remember(animationAngle) {
// We only need this animation for second rotation
if (animationAngle >= 360) {
// Reversed linear interpolation between 0..30 degrees, transformed into 0..1
(animationAngle % 30) / 30
} else -1f
}
Spacer(...
.drawBehind {
...
hours.forEach {
if (!dotsVisibility[it]) return@forEach
val degree = it * 30f
rotate(degree) {
val start = Offset(size.width / 2, 0f)
val end = Offset(size.width / 2, strokeWidth)
drawLine(
val dotsVisibility = remember(currentHour) {
hours.map { index ->
when {
index > currentHour -> false
index > currentHour - 12 -> true
else -> false
}
}
}
Spacer(...
.drawBehind {
...
val endOffset = Offset(
size.width / 2,
size.height / 2 - calculateClockHandLength( size.height / 2, currentHour)
)
...
rotate(animationAngle, pivot = center) {