Many of the Animation APIs commonly accept parameters for customizing their
behavior.
Customize animations with the
AnimationSpec
parameter
Most animation APIs allow developers to customize animation specifications by an
optional
AnimationSpec
parameter.
val alpha: Float by animateFloatAsState(
targetValue = if (enabled) 1f else 0.5f,
// Configure the animation duration and easing.
animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing)
)
There are different kinds of
AnimationSpec
for creating different types of
animation.
Create physics-based animation with
spring
spring
creates a physics-based animation between start and end values. It
takes 2 parameters:
dampingRatio
and
stiffness
.
dampingRatio
defines how bouncy the spring should be. The default value is
Spring.DampingRatioNoBouncy
.
Figure 1.
Setting different spring damping ratios.
stiffness
defines how fast the spring should move toward the end value. The
default value is
Spring.StiffnessMedium
.
Figure 2.
Setting different spring stiffness
val value by animateFloatAsState(
targetValue = 1f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioHighBouncy,
stiffness = Spring.StiffnessMedium
)
)
spring
can handle interruptions more smoothly than duration-based
AnimationSpec
types because it guarantees the continuity of velocity when
target value changes amid animations.
spring
is used as the default
AnimationSpec by many animation APIs, such as
animate*AsState
and
updateTransition
.
For example, if we apply a
spring
config to the following animation that is driven by user touch, when interrupting the animation as its progressing, you can see that using
tween
doesn't respond as smoothly as using
spring
.
Figure 3.
Setting
tween
vs
spring
specs for animation, and interrupting it.
Animate between start and end values with easing curve with
tween
tween
animates between start and end values over the specified
durationMillis
using an easing curve.
tween
is short for the word between - as it goes
between
two values.
You can also specify
delayMillis
to postpone the start of the animation.
val value by animateFloatAsState(
targetValue = 1f,
animationSpec = tween(
durationMillis = 300,
delayMillis = 50,
easing = LinearOutSlowInEasing
)
)
See
Easing
for more information.
Animate to specific values at certain timings with
keyframes
keyframes
animates based on the snapshot values specified at different
timestamps in the duration of the animation. At any given time, the animation
value will be interpolated between two keyframe values. For each of these
keyframes, Easing can be specified to determine the interpolation curve.
It is optional to specify the values at 0 ms and at the duration time. If you do
not specify these values, they default to the start and end values of the
animation, respectively.
val value by animateFloatAsState(
targetValue = 1f,
animationSpec = keyframes {
durationMillis = 375
0.0f at 0 with LinearOutSlowInEasing // for 0-15 ms
0.2f at 15 with FastOutLinearInEasing // for 15-75 ms
0.4f at 75 // ms
0.4f at 225 // ms
}
)
Repeat an animation with
repeatable
repeatable
runs a duration-based animation (such as
tween
or
keyframes
)
repeatedly until it reaches the specified iteration count. You can pass the
repeatMode
parameter to specify whether the animation should repeat by
starting from the beginning (
RepeatMode.Restart
) or from the end
(
RepeatMode.Reverse
).
val value by animateFloatAsState(
targetValue = 1f,
animationSpec = repeatable(
iterations = 3,
animation = tween(durationMillis = 300),
repeatMode = RepeatMode.Reverse
)
)
Repeat an animation infinitely with
infiniteRepeatable
infiniteRepeatable
is like
repeatable
, but it repeats for an infinite amount
of iterations.
val value by animateFloatAsState(
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(durationMillis = 300),
repeatMode = RepeatMode.Reverse
)
)
In tests using
ComposeTestRule
,
animations using
infiniteRepeatable
are not run. The component will be
rendered using the initial value of each animated value.
Immediately snap to end value with
snap
snap
is a special
AnimationSpec
that immediately switches the value to the
end value. You can specify
delayMillis
in order to delay the start of the
animation.
val value by animateFloatAsState(
targetValue = 1f,
animationSpec = snap(delayMillis = 50)
)
Set a custom easing function
Duration-based
AnimationSpec
operations (such as
tween
or
keyframes
) use
Easing
to adjust an animation's fraction. This allows the animating value to
speed up and slow down, rather than moving at a constant rate. Fraction is a
value between 0 (start) and 1.0 (end) indicating the current point in the
animation.
Easing is in fact a function that takes a fraction value between 0 and 1.0 and
returns a float. The returned value can be outside the boundary to represent
overshoot or undershoot. A custom Easing can be created like the code below.
val CustomEasing = Easing { fraction -> fraction * fraction }
@Composable
fun EasingUsage() {
val value by animateFloatAsState(
targetValue = 1f,
animationSpec = tween(
durationMillis = 300,
easing = CustomEasing
)
)
// ……
}
Compose provides several built-in
Easing
functions that cover most use cases.
See
Speed - Material Design
for more
information about what Easing to use depending on your scenario.
FastOutSlowInEasing
LinearOutSlowInEasing
FastOutLinearEasing
LinearEasing
CubicBezierEasing
- See more
Animate custom data types by converting to and from
AnimationVector
Most Compose animation APIs support
Float
,
Color
,
Dp
, and other basic data
types as animation values by default, but you sometimes need to animate
other data types including your custom ones. During animation, any animating
value is represented as an
AnimationVector
. The value is converted into an
AnimationVector
and vice versa by a corresponding
TwoWayConverter
so that
the core animation system can handle them uniformly. For example, an
Int
is
represented as an
AnimationVector1D
that holds a single float value.
TwoWayConverter
for
Int
looks like this:
val IntToVector: TwoWayConverter<Int, AnimationVector1D> =
TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })
Color
is essentially a set of 4 values, red, green, blue, and alpha, so
Color
is converted into an
AnimationVector4D
that holds 4 float values. In
this manner, every data type used in animations is converted to either
AnimationVector1D
,
AnimationVector2D
,
AnimationVector3D
, or
AnimationVector4D
depending on its dimensionality. This allows different
components of the object to be animated independently, each with their own
velocity tracking. Built-in converters for basic data types can be accessed
using converters such as
Color.VectorConverter
or
Dp.VectorConverter
.
When you want to add support for a new data type as an animating value, you can
create your own
TwoWayConverter
and provide it to the API. For example, you
can use
animateValueAsState
to animate your custom data type like this:
data class MySize(val width: Dp, val height: Dp)
@Composable
fun MyAnimation(targetSize: MySize) {
val animSize: MySize by animateValueAsState(
targetSize,
TwoWayConverter(
convertToVector = { size: MySize ->
// Extract a float value from each of the `Dp` fields.
AnimationVector2D(size.width.value, size.height.value)
},
convertFromVector = { vector: AnimationVector2D ->
MySize(vector.v1.dp, vector.v2.dp)
}
)
)
}
The following list includes some built-in
VectorConverter
s:
Recommended for you