compose-animations
GitHub指导Jetpack Compose动画API选型与实现,涵盖可见性、属性过渡及状态协调,确保生命周期匹配与性能优化。
Trigger Scenarios
Install
npx skills add chrisbanes/skills --skill compose-animations -g -y
SKILL.md
Frontmatter
{
"name": "compose-animations",
"description": "Use when writing or reviewing Jetpack Compose motion: visibility enter\/exit, animating one property toward a target, color or size transitions, multiple properties from one state, switching composable content, or choosing between AnimatedVisibility, animate*AsState, rememberTransition, AnimatedContent, and Crossfade."
}
Compose: animations
Core principle
Pick the smallest API that expresses the motion and its lifecycle.
Procedure
- Identify the job: show or hide a subtree, animate one value, coordinate values from one state, resize content, swap content, or handle user-driven motion.
- Choose the matching API from the table. Prefer target-state APIs; use
Animatableonly when gestures, interruption, or imperative control require it. - Check lifecycle: an alpha animation keeps content composed;
AnimatedVisibilityremoves it after exit. Do not use a fade when unmounting is required. - For
AnimatedContent, render from the content lambda target and choose acontentKeyonly when visual identity differs from payload equality. Read AnimatedContent identity for state-holder details. - Keep animated
Statein layout or draw block modifiers when it changes at frame rate; route deeper diagnosis to Compose performance. - Use Navigation Compose transitions for destination swaps it owns, and dedicated libraries for art-based motion.
- Finish when the API, lifecycle, and content identity match the UI, no simpler API fits, and the relevant behavior is verified.
API choice
| Need | Prefer |
|---|---|
| Show/hide a subtree with enter/exit semantics | AnimatedVisibility |
| One value follows state | animate*AsState |
| Several values follow one boolean, enum, or sealed state | rememberTransition plus child animations |
| Child size changes | Modifier.animateContentSize() |
| Different composable trees fill one region | AnimatedContent, or Crossfade for the simple case |
| Drag, fling, interruption, or imperative control | Animatable |
Use an AnimationSpec when the default motion is wrong and a distinct label when multiple animations need tooling visibility.
val width by animateDpAsState(
targetValue = if (expanded) 200.dp else 56.dp,
animationSpec = spring(dampingRatio = 0.7f),
label = "fabWidth",
)
For values that must remain synchronized, define them on one transition rather than several independent animate*AsState calls:
val transition = rememberTransition(targetState = phase, label = "phase")
val alpha by transition.animateFloat(label = "alpha") { target ->
if (target == Phase.Visible) 1f else 0f
}
val offset by transition.animateDp(label = "offset") { target ->
if (target == Phase.Visible) 0.dp else 24.dp
}
For animated fills, prefer drawBehind { drawRect(color.value) } over a value-form background when the color updates every frame. For an API ambiguity, start with the official Choose an animation API guide; use rememberInfiniteTransition for repeating cycles and SeekableTransitionState for seekable or test-controlled progress.
When not to use this skill
- For side-effect timing or click-launched work, use Compose state and effects.
- For deep state-read or recomposition diagnosis, use Compose performance.
Version History
-
2026.8.24
Current 2026-08-27 17:15
精简了技能指令的冗余描述,优化了核心原则和审查流程的表达清晰度。
-
2026.8.16
2026-08-19 19:31
更新审查步骤第4点:明确 AnimatedContent.contentKey 应基于视觉形状而非数据变化选择;增加关于 animateFloatAsState 仅改变透明度且保留组件树的说明。
-
2026.8.5
2026-08-16 02:44
将多个细粒度的 Kotlin 和 Compose 技能整合为五个自包含集群,更新全局路由和迁移文档。
- 2026.7.21 2026-07-24 12:24


