https://kotlinlang.org logo
#compose
Title
# compose
t

Thiago

03/04/2021, 2:27 PM
Hi folks. Has Compose Animations the interval concept where I can run another animation based on parent progress? Or do I need create each separated animation and stay checking parent progress to start each at time? E.g:
Copy code
// Sample 1
.listenParent { progress ->
    if (progress < 0.1f) // update opacity state to start opacity animation
    else if (progress < 0.25f) // update width state to start width animation
    ...
}

// Sample 2
@Composable
fun OpacityComposable(parentProgress: Float = 0f, parentTimeMs: Long = 300) {
    val target = (parentProgress / 0.1f).coercIn(0f, 1f)
    // Ignore the unexpected behavior where the parent restart will first animate opacity to 0f before 1f
    val opacity = animateFloatAsState(
        targetValue = target,
        animationSpec = tween(
            durationMillis = parentTimeMs * 0.1f, // Is it the way to keep time sync between them?
            easing = LinearOutSlowInEasing // To have an independent curve 
        )
    )
}
👀 3
d

Doris Liu

03/04/2021, 8:40 PM
This is a pretty cool use case. 🙂 Thanks for sharing! We don't have an API tailored for this use case yet. But we are looking into building support for coordinating animations in general. So use cases like this are very helpful. 👍 Is the parent progress driven by gesture (i.e. non-monotonic) or time (i.e. monotonic)? • If it's driven by gesture, I'd recommend taking a look at
TargetBasedAnimation
: https://developer.android.com/jetpack/compose/animation#targetbasedanimation It's the stateless animation that backs up our high level animations. This may take some effort, because... with more power comes more responsibility. 🤣 Alternatively, you could do what you did in sample2, and use the default or a faster spring() to fake the impression of following the progress change. I suspect that should be pretty smooth, though not exactly adhering to the timeline. • If the progress is driven strictly by time. Consider using delay for the animations on the timeline.
❤️ 2
Copy code
@Composable
fun <T, V: AnimationVector> childAnimation(
    initialValue: T, targetValue: T, typeConverter: TwoWayConverter<T, V>,
    progress: Float, parentDuration: Long, startProgress: Float, endProgress:
Float) : T {
    val duration = remember(parentDuration, startProgress, endProgress) {
        (parentDuration * (endProgress - startProgress)).roundToInt()
    }
    val delay = remember(parentDuration, startProgress) { (parentDuration * startProgress).roundToInt() }
    val animation = remember(initialValue, targetValue, typeConverter, duration, delay) {
        TargetBasedAnimation(
            initialValue = initialValue,
            targetValue = targetValue,
            typeConverter = typeConverter,
            animationSpec = tween(
                durationMillis = duration,
                delayMillis = delay,
                easing = LinearOutSlowInEasing // To have an independent curve
            )
        )
    }

    val playTimeNanos = remember(parentDuration, progress) {
        (progress * parentDuration * 1_000_000).toLong()
    }
    return animation.getValueFromNanos(playTimeNanos)
}
🦠 3
Something like this could work for all child animations. 🙂
t

Thiago

03/04/2021, 8:58 PM
Amazing 😍. I'll try. Thanks again Doris!
d

Doris Liu

03/04/2021, 8:59 PM
Cool! Let me know how that works for you. Would love to see what you build! 😄
6 Views