Im animating my sine curve indefinetly horizontal...
# compose
a
Im animating my sine curve indefinetly horizontaly, any better ideas how to do it ?
Copy code
LaunchedEffect(key1 = Unit, block = {
    while (isActive) {
        delay(50)
        horizontalAnimation.value = horizontalAnimation.value + 2.dp
    }
})
i animate the amplitude like this
Copy code
val transition = rememberInfiniteTransition()
val amplitudeAnimation = transition.animateFloat(
    initialValue = -1f, targetValue = 1f, animationSpec = InfiniteRepeatableSpec(
        tween(3000),
        repeatMode = RepeatMode.Reverse
    )
)
a
withFrame[Nanos|Millis] { frameTime ->
is a better alternative than
delay,
then you can calculate the amount to animate by based on how much time elapsed since the previous frame.
delay
will be janky and not align with frames.
👍 1
@Doris Liu would probably give some more idiomatic advice for the higher level animation system
j
Is there ever a time when delay is the right function in a launched effect? Maybe it should be a warning or something?
a
It depends on whether you're delaying for animation or for some other pulse. The false positives might be worse than the benefits
j
Just curious, maybe I'm not awake enough yet on a Sunday morning, but why would you delay if not for (1) an animation or (2) sideways data loading which is an terrible practice that should be warned against anyway.
d
withFrame[Nanos|Millis]
makes total sense here for calculating the offset, as you probably want a constant velocity. One thing to watch out for is the rounding error, as compounding rounding error on each frame may produce a subtle drift. Alternatively, an equally viable option would be to have an animation in a while-loop to take care of that calculation/rounding for you. It could be something like:
Copy code
LaunchedEffect(...) {
        val horizontalAnimation = AnimationState(Dp.VectorConverter, 0.dp)
        while(isActive) {
            horizontalAnimation.animateTo(
                horizontalAnimation.value + 2.dp,
                tween(50, easing = LinearEasing),
                sequentialAnimation = true
            ) {
                // Update something with the animation value
            }
        }
    }
Re
delay
: if you want to do something once per interval, and the interval is long enough (say 5 seconds) that being off by one frame (from not aligning with frame time) is not a concern. Seems like
delay
would be a convenient way to achieve that.
j
But why would you want to do that? And shouldn't you be subscribed to a clock at that point, rather than using delay? Otherwise, you are not going to behave correctly when someone accelerates time (eg. unit test) and a variety of other circumstances where the delay approach is fragile.
d
Accelerating time in unit-tests shouldn't be a problem for
delay
, assuming you use the
TestCoroutineDispatcher
or implement
DelayController
correctly: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-delay-controller/advance-time-by.html
a
thx for all the valuable info. this slack channel is awesome 🙏
K 1