From 600687ab5649f593fc00962444b7cda9c660fb77 Mon Sep 17 00:00:00 2001 From: cottongin Date: Wed, 18 Mar 2026 04:10:23 -0400 Subject: [PATCH] feat: add fade-in and shorten restart pause for ticker Text now fades in over 300ms when it reappears instead of popping in. Restart pause shortened from 1.5s to 0.5s. Initial 1.5s delay kept. Switched from infiniteRepeatable to Animatable + LaunchedEffect loop for independent control over initial vs subsequent cycles. Made-with: Cursor --- .../ui/screens/nowplaying/NowPlayingScreen.kt | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/xyz/cottongin/radio247/ui/screens/nowplaying/NowPlayingScreen.kt b/app/src/main/java/xyz/cottongin/radio247/ui/screens/nowplaying/NowPlayingScreen.kt index 25613f0..35db5ed 100644 --- a/app/src/main/java/xyz/cottongin/radio247/ui/screens/nowplaying/NowPlayingScreen.kt +++ b/app/src/main/java/xyz/cottongin/radio247/ui/screens/nowplaying/NowPlayingScreen.kt @@ -5,13 +5,10 @@ import android.content.res.Configuration import android.graphics.BitmapFactory import androidx.compose.animation.AnimatedContent import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.LinearEasing -import androidx.compose.animation.core.RepeatMode -import androidx.compose.animation.core.animateFloat -import androidx.compose.animation.core.infiniteRepeatable -import androidx.compose.animation.core.keyframes -import androidx.compose.animation.core.rememberInfiniteTransition import androidx.compose.animation.core.tween +import kotlinx.coroutines.delay import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.togetherWith @@ -478,30 +475,36 @@ private fun TickerText( val velocityPxPerMs = with(density) { velocityDpPerSecond.dp.toPx() } / 1000f val totalScrollPx = textWidthPx + containerWidthPx val scrollMs = (totalScrollPx / velocityPxPerMs).toInt() - val initialDelayMs = 1500 - val durationMs = initialDelayMs + scrollMs - val transition = rememberInfiniteTransition(label = "ticker") - val offset by transition.animateFloat( - initialValue = 0f, - targetValue = 0f, - animationSpec = infiniteRepeatable( - animation = keyframes { - durationMillis = durationMs - 0f at 0 using LinearEasing - 0f at initialDelayMs using LinearEasing - -totalScrollPx at durationMs using LinearEasing - }, - repeatMode = RepeatMode.Restart - ), - label = "ticker" - ) + val offset = remember { Animatable(0f) } + val alpha = remember { Animatable(0f) } + + LaunchedEffect(textWidthPx, containerWidthPx) { + offset.snapTo(0f) + alpha.snapTo(0f) + alpha.animateTo(1f, tween(300)) + delay(1500L) + + while (true) { + offset.animateTo( + -totalScrollPx, + tween(scrollMs, easing = LinearEasing) + ) + offset.snapTo(0f) + alpha.snapTo(0f) + alpha.animateTo(1f, tween(300)) + delay(500L) + } + } Box( modifier = Modifier .wrapContentWidth(align = Alignment.Start, unbounded = true) .align(Alignment.CenterStart) - .graphicsLayer { translationX = offset } + .graphicsLayer { + translationX = offset.value + this.alpha = alpha.value + } ) { if (strokeColor != null) { Text(