前言
简单动画推荐使用 animate*AsState
或 rememberInfiniteTransition
,复杂交互动画则适合 Animatable
或 updateTransition
。
个人比较喜欢使用Animatable
,灵活方便。
单属性动画
animate*AsState
使用 animate*AsState
系列 API
这是最基础的动画方式,通过监听状态变化自动生成动画值,适用于简单的属性动画。
1 | import androidx.compose.animation.core.animateFloatAsState |
rememberInfiniteTransition
使用 rememberInfiniteTransition
实现无限动画
适用于需要无限循环的动画,如加载指示器。
1 | import androidx.compose.animation.core.LinearEasing |
Animatable
循环播放
1 | import androidx.compose.animation.core.Animatable |
单次播放
1 | val animProgress = remember { Animatable(0.5f) } |
updateTransition
使用 updateTransition
管理多状态过渡
适合在多个状态之间平滑过渡,如组件的展开 / 折叠 / 隐藏状态切换。
1 | import androidx.compose.animation.core.animateDp |
组合动画
1 | import androidx.compose.animation.core.Animatable |
动画类型
缓动动画
tween
缓动曲线(Easing),用于控制动画的速度变化节奏。
它们基于贝塞尔曲线(Cubic Bezier)实现,能让动画效果更符合物理规律或视觉预期,避免机械感的匀速运动。
1 | tween(durationMillis = 1200, easing = LinearEasing) |
easing值
默认是FastOutSlowInEasing
1 | // 先快速加速,然后缓慢减速到停止 |
单次动画时长2秒,线性匀速
1 | animation = tween(2000, easing = LinearEasing) |
弹簧动画
弹簧动画(不能用在infiniteRepeatable中)
1 | val animProgress = remember { Animatable(50f) } |
关键帧动画
1 | animation = keyframes { |
跳变
1.2秒后直接跳变
1 | animation = snap(1200) |
循环播放
1 | animProgress.animateTo( |
在 Jetpack Compose 中,infiniteRepeatable()
是用于创建无限循环动画的关键函数,通常配合 rememberInfiniteTransition
使用。它的参数用于控制循环方式、动画曲线、重复次数等,以下是详细说明:
函数签名
1 | fun <T> infiniteRepeatable( |
核心参数说明
动画类型
animation: AnimationSpec<T>
(必填)
作用:定义单次动画的行为(如时长、缓动曲线等)
常用值:
tween()
:指定固定时长的动画(最常用)spring()
:弹簧物理效果的动画keyframes()
:关键帧动画snap()
:无动画,直接跳变
循环方式
repeatMode: RepeatMode
(可选,默认 Restart
)
作用:定义每次循环的方式
取值:
RepeatMode.Restart
:每次循环从初始值重新开始RepeatMode.Reverse
:交替反向播放(如从0→1→0→1…)
示例:先正向播放,再反向播放,循环往复
1 | repeatMode = RepeatMode.Reverse |
延迟
initialStartOffset: StartOffset
(可选,默认 StartOffset(0)
)
作用:定义动画首次启动的延迟或偏移
使用场景:
- 延迟首次动画开始时间
- 让多个循环动画错开启动(实现错开的波浪效果)
1 | // 首次启动延迟500ms |
注意:
offsetMillis
是相对于动画总时长的偏移(如2000ms动画,偏移1000ms即从中间开始)
完整示例
以下是一个结合 infiniteRepeatable
参数的旋转+缩放动画:
1 |
|
关键注意点
infiniteRepeatable
必须配合rememberInfiniteTransition
使用,不能直接用于animate*AsState
repeatMode = Reverse
时,动画会在initialValue
和targetValue
之间来回切换- 多个动画可以共享同一个
infiniteTransition
,通过initialStartOffset
实现错开效果 - 若需要停止无限动画,可通过控制
rememberInfiniteTransition
的生命周期(如用LaunchedEffect
的key
参数)
通过组合这些参数,可以实现各种复杂的循环动画效果,如加载指示器、呼吸效果、旋转动画等。