Animations are useful to present and underline changes on the GUI; they must be used judiciously and must not be abused to prevent performance penalty.
There are two levels of API:
- The high level API that has been introduced recently (and is experimental)
- The low level API
Low level API
animate*AsState
Rather than changing instantly a value for the GUI, it could be esthetically better to change it progressively.
Delegate of the form animate*AsState are proposed to change a value with a duration (interpolation is used to build intermediary frames).
Several kinds of values can be changed with these delegates:
- animateFloatAsState
- animateDpAsState
- animateIntAsState
- animateIntOffsetAsState
- animateOffsetAsState
- animateReactAsState
- animateStateAsState
- animateColorAsState
- ...
One can also use animateValueAsState with a customized TwoWayConverter to create an AnimationVector allowing the animation.
The animationSpec parameter can be used to customize the transition (spring, tween, keyframes, repeatable, infiniteRepeatable, snap), one can choose an easing functions for duration-based transitions (it defines the progression of the transition over the time).
Example: a component displaying a color that cycles when we click on it
val ROYGBIV = arrayOf(Color.Red, Color(0xffff8000), Color.Yellow, Color.Green, Color.Blue, Color(0xff4b00820), Color(0xff7f007f)) @Composable fun AnimateColor() { var step by remember { mutableStateOf(0) } val animationSpec = tween<Color>(durationMillis = 1000, delayMillis = 10, easing = FastOutSlowInEasing) val color by animateColorAsState(targetValue = ROYGBIV[step], animationSpec = animationSpec) val interactionSource = remember { MutableInteractionSource() } Box(Modifier.fillMaxSize().background(color).clickable(interactionSource = interactionSource, indication = null) { step = (step + 1) % ROYGBIV.size }) { } }
Alternatively if we want to use an imperative style to change a property, one can use Animatable :
var step by remember { mutableStateOf(0) } val color = remember { Animatable(ROYGBIV[0]) } LaunchedEffect(step) { color.animateTo(ROYGBIV[step]) } Box(Modifier.fillMaxSize().background(color).clickable(interactionSource = interactionSource, indication = null) { step = (step + 1) % ROYGBIV.size }) { }