官方动画线文档讲 API;本文强调 「状态驱动动画」 、默认过渡与可访问性 、以及 graphicsLayer 与布局 pass 的边界。
配套示例

AnimationLabScreen.kt:宽度比例、AnimatedVisibility、graphicsLayer { rotationZ }。
1. animateFloatAsState:谁在驱动帧?
- 驱动源是 State :
targetValue变化 → 动画在帧间 插值 → 组合读到的 float 连续变化 → 依赖该值的 UI 重新计算。若这个值参与fillMaxWidth(fraction)等布局参数,会触发重新测量;若只参与graphicsLayer.alpha/rotationZ等图层属性,通常更偏绘制路径。 label参数:给动画调试/Studio 轨迹用,养成命名习惯。- 适用边界 :
animate*AsState适合「一个状态 → 一个目标值」的简单动画;需要手动启动、取消、串行动画时,用Animatable更合适。
避坑
- 把 网络结果 直接绑
targetValue且 无初始过渡 :首次可能出现「从 0 猛跳到目标」;需要SpringSpec或 初始值对齐。 - 高频
targetValue抖动(每帧传感器):先做 low-pass / sample / distinctUntilChanged,不要把所有原始数据直接塞给 Compose 动画。
2. AnimatedVisibility:别塞重 IO
enter/exit 组合 fadeIn + expandVertically 很常见。不要在 visibility 块里启动无关联的长请求;可见性只表达 UI 存在性。
无障碍 :突然出现/消失的大块,确认 TalkBack 焦点顺序 不会跳进「尚未可见」的区域。
状态保留 :AnimatedVisibility(visible = false) 的内容会在退出动画完成后离开 composition;内部 remember 状态也会随之释放。若内容再次出现仍需保留状态,应把状态上提到外层或 ViewModel。
3. graphicsLayer { }:为什么省布局?
rotationZ/scaleX/alpha/clip在 layer 上常可走 绘制路径 而不触发布局(视具体 Modifier 链而定)。- 代价 :过度
clip+ 大模糊阴影 → 离屏渲染 成本;列表 item 内慎用全屏模糊。 - 注意 :
graphicsLayer本身不等于动画。它只是把图层属性设为某个值;若要平滑旋转,应先用animateFloatAsState/Animatable产生连续值,再把该值写进rotationZ。
避坑
- 在
graphicsLayer里读 每帧变化 的大对象:仍可能拖慢 render thread;动画状态应 primitive 化。 alpha = 0f只是视觉透明,不等于从语义树、焦点链路或点击链路消失;真正显隐优先用AnimatedVisibility或条件组合。
4. 与 Lazy 列表 item 动画的关系
列表 item 位移动画依赖 稳定 identity(key) ;动画篇与列表篇要 交叉阅读,否则会出现「飞错行」。
API 名称会随 Compose 版本演进:旧资料常见 Modifier.animateItemPlacement();较新的 Foundation Lazy 列表更推荐查看当前版本文档中的 Modifier.animateItem() / item placement 相关 API。写博客时不要死记某个函数名,关键是记住:key 稳定,动画才知道哪一行从哪里移动到哪里。
5. 自检清单
animateFloatAsState的targetValue是否来自「业务状态」而非每帧随机传感器直绑(若绑传感器是否做了平滑)?AnimatedVisibility内 是否避免启动与可见性无关的长生命周期任务(仅控制 UI 显隐)?graphicsLayer里驱动的属性是否尽量为 primitive(float),避免持有大对象参与每帧逻辑?- 列表 item 动画是否与 稳定
key(04 篇)一起验证过,并核对了当前 Compose 版本的推荐 API?
参考答案(复习用)
- 应状态驱动 。
targetValue = if (expanded) 1f else 0f;传感器类数据应先 low-pass 或采样,避免 target 每帧剧变导致插值跟不上或耗电。 - 应避免 。进入
visible可LaunchedEffect拉短请求;不要在enter/exit里挂永不取消的循环;重 IO 仍归 ViewModel。需要保留的状态放到外层。 - 应尽量 primitive 。
rotationZ、alpha等用Float;大对象放remember或 VM,动画块里只读其导出的标量。透明不等于不可点,语义也要一起考虑。 - 是 。先用正确
key验证列表 identity,再打开 item 动画;API 名称以当前 Compose Foundation 文档为准。
源码仓库 :ComposeDemo(分支
main)