Is this the correct way to have a cyclic animation...
# compose-android
m
Is this the correct way to have a cyclic animation with different animation specs between two states? I feel like there should be something more convenient.
Copy code
val animationProgress = remember { Animatable(initialAnimationProgress) }
LaunchedEffect(Unit) {
    while (isActive) {
        if (animationProgress.value == 0f) {
            animationProgress.animateTo(
                targetValue = 1f,
                animationSpec = tween(4000, easing = LinearEasing),
            )
            delay(4000)
        } else {
            animationProgress.animateTo(
                targetValue = 0f,
                animationSpec = tween(1200, easing = FastOutLinearInEasing),
            )
            delay(1200)
        }
    }
}
sounds like
rememberInfiniteTransition
could be a fit for this use case.
m
Does it allow to have different animation specs depending on the direction of progress?
I don't see it
d
How do you mean depending on "direction of progress"?
m
Animation from 0 to 1 and from 1 to 0
d
you could use
keyframes
to go back and forth and then just set the
RepeatMode.Restart
Copy code
@Sampled
@Composable
fun InfiniteTransitionAnimateValueSample() {
    // Creates an [InfiniteTransition] instance to run child animations.
    val infiniteTransition = rememberInfiniteTransition()
    // Infinitely animate a Dp offset from 0.dp to 100.dp
    val offsetX by infiniteTransition.animateValue(
        initialValue = 0.dp,
        targetValue = 100.dp,
        typeConverter = Dp.VectorConverter,
        animationSpec = infiniteRepeatable(
            animation = keyframes {
                durationMillis = 500
                0.dp at 200 // ms
                80.dp at 300 using FastOutLinearInEasing
            }
            // Use the default RepeatMode.Restart to start from 0.dp after each iteration
        )
    )

    Box(Modifier.offset(x = offsetX)) {
        // Content goes here
    }
}
(Haven't tried this specific usecase but it feels like it should work)
m
Hmmm, the problem is that it allows only for time based animations. Physics ones cannot be used in infinite transition. I should've included that in my example
I could probably emulate it with a custom interpolator. But then I come to a point where a solution with an
Animatable
and
LaunchedEffect
is easier to maintain
j
A few months back I need to animate around 7 balls bouncing from outside of the screen bounds (lower left corner) into view and then have them animate back out of screen. The issue was each ball has a different rotation and velocity, from one another. I had to achieve this with seven animatables inside of a
LaunchedEffect
I don’t know if it’s correct but it works.
I had considered going this route and calculating the individual x and y offsets manually but found my current approach just as functional. I do wonder if using withInfiniteAnimationFrameMillis is more performant, and would like to investigate it in the future.