Anyone have ideas of how to animate a value the sh...
# compose-android
d
Anyone have ideas of how to animate a value the shortest path, in a range that can wrap? E.g 0..360 where I can go from 10 to 350 by passing through 0. I've been looking at animate*AsState, but seems like they only act on closed ranges.
One idea I has was to use keyframes and then snap, but it does not feel natural. Another idea: Would be to get it as a vector. E.g 10 to 350 would be (-20) and then animating that and adding it to result.
t
How long do you need it to run for? If not forever and ever.. can you just use a really long closed range, but mod the value by 360 in between application? Most code that deals with anything radial (e.g. drawing arcs, etc), will handle 1004π just as well as 2π.
d
Well I'd like no limitation
Came up with this solution yesterday:
Copy code
val sliderInput = remember { mutableFloatStateOf(0f) }
val sliderAnimated = remember { Animatable(sliderInput.floatValue) }
LaunchedEffect(sliderInput.floatValue) {
    launch {
        val vector = shortestVector(
            sliderAnimated.value,
            sliderInput.floatValue
        )
        sliderAnimated.animateTo(
            sliderAnimated.value + vector,
            animationSpec = tween(2000)
        )
    }
}

Slider(
    value = sliderAnimated.value.mod(1f),
    onValueChange = {
        sliderInput.floatValue = it
    },
    valueRange = 0f..1f
)
Text(text = "sliderAnimated: ${sliderAnimated.value}!")
Copy code
fun shortestVector(current: Float, newValue: Float): Float {
    val diff = newValue - current
    return when {
        diff > 0.5 -> diff - 1f
        diff < -0.5 -> diff + 1f
        else -> diff
    }
}
Basically I needed the current animation value when launching a new animation. This wasn't possible with
animate*AsState
Here I found a resource on other ways of having value-based animation