Animation In Compose Series (Part 2) — Understanding AnimationSpec
Another Article in my Series of Animations in Compose. Do check out the previous Article on Animated Visibility and Animated Content.
Here in this Article we will understand in depth about AnimationSpec clearly and see how to use it as there are many functions and composable which require AnimationSpec as a parameter.
So let's see what are those.
There are 2 predefined AnimationSpec
- Tween
- Spring
Tween
Tween is a simple animation that works on easing. In simple words, tween works in this way.
Let’s say we are animating a line with animationSpec as a tween it will move from one point to another in a linear way depending on the Easing given.
Easing allows value to speed up and slow down, rather than moving at a constant.
As you can see here different Easing have different values. They are the same as the Animation Interpolators we had in XML animations.
You can also create your own Easing by using the CubicBezierEasing class.
Example of how to use Tween
@Composable
fun TweenExample() {
var isEnabled by remember {
mutableStateOf(false)
}
val pathAnimation = animateFloatAsState(
targetValue = if (!isEnabled) 0f else 1f,
animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing),
label = "Tween FastOutSlowInEasing Animation"
)
}
Spring
Spring is a Physics-based animation that just works like it says “Like a Spring”. it gives a bouncy animation depending upon 2 things specified one is DampingRatio and the other is Stiffness.
Damping Ratio — It defines how bouncy the animation should be.
Stiffness — This defines how fast the animation should move toward the end value.
Here is how it looks with different dampingRatio —
The default dampingRatio for spring is Spring.DampingRatioNoBouncy
Here is how it looks with different stiffness —
Here is how you would use it.
@Composable
fun SpringExample() {
var isEnabled by remember {
mutableStateOf(false)
}
val pathAnimation = animateFloatAsState(
targetValue = if (!isEnabled) 0f else 1f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioHighBouncy,
stiffness = Spring.StiffnessLow
),
label = "Tween FastOutSlowInEasing Animation",
)
LaunchedEffect(key1 = Unit) {
isEnabled = true
}
Canvas(modifier = Modifier.fillMaxSize()) {
drawCircle(
color = Color.Black,
radius = 90f,
center = Offset((pathAnimation.value * 600f) + 100f, 100f)
)
}
}
Now these were some predefined AnimationSpec but how to use more than that.
That’s when Key Frames comes to act.
KeyFrames
keyframes simply means we can animate based on the values at different timestamps. You can also specify the easing on a particular time stamp.
Here is how you would use it.
@Composable
fun KeyframeExample() {
var isEnabled by remember {
mutableStateOf(false)
}
val pathAnimation = animateFloatAsState(
targetValue = if (!isEnabled) 0f else 1f,
animationSpec = keyframes {
//total duration
durationMillis = 5000
0.0f at 0 with LinearOutSlowInEasing// for 0-15 ms
0.2f at 1000 // for 15-75 ms
0.5f at 2500 // ms
0.7f at 4000 with EaseInBounce// ms
},
label = "KeyframeExample",
)
LaunchedEffect(key1 = Unit) {
isEnabled = true
}
Canvas(modifier = Modifier.fillMaxSize()) {
drawCircle(
color = Color.Black,
radius = 40f,
center = Offset((pathAnimation.value * 700f) + 100f, 100f)
)
}
}
Here if you see the map
keyframes {
//total duration
durationMillis = 5000
0.0f at 0 with LinearOutSlowInEasing// for 0-15 ms
0.2f at 1000 // for 1000-2500 ms
0.5f at 2500 // ms
0.7f at 4000 with EaseInBounce// ms
}
durationMills is the total duration of the Animation
The float value at the start 0.2f at 1000 means that from 1000 ms to 2500 ms, the animation will cover 20 percent of the total value as per the above example as the target value is from 0 to 1.
From 1000 ms to 2000 ms the animation will cover the value from 0.2 to 0.5
The added advantage here is you can specify the easing with that like we did below
0.7f at 4000 with EaseInBounce
As you can see above at the last movement the circle is doing a bounce animation that is due to the last part as we added EaseInBounce animation at the last keyframe.
Some more tips at the end.
Wherever there is a requirement for an AnimationSpec for animation here is how you could do Infinite animations.
Infinite Animations from AnimationSpec
val value by animateFloatAsState(
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis = 2000),
repeatMode = RepeatMode.Reverse
)
)
Repeatable Animations from AnimationSpec
val value by animateFloatAsState(
targetValue = 1f,
animationSpec = repeatable(
iterations = 10,
animation = tween(durationMillis = 1000),
repeatMode = RepeatMode.Reverse
)
)
Follow me and Stay tuned for more such content. Feedback would be appreciated as always.
A clap also would be appreciated but a read would be enough.
Thank You and have a Happy coding Journey. :)
You can connect with me at LinkedIn — Bharat Kumar
Here is the GitHub repo with samples of Animation — https://github.com/PalankiBharat/Compose-Animation-Samples.git