协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
compose-animations【开发与工程】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.
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
Pick the smallest API that expresses the motion and its lifecycle.
Animatable only when gestures, interruption, or imperative control require it.AnimatedVisibility removes it after exit. Do not use a fade when unmounting is required.AnimatedContent, render from the content lambda target and choose a
contentKey only when visual identity differs from payload equality. In a
swap between distinct items, keep the target value as the identity (the
default) or key by a stable item ID; do not collapse different items to a
shared presence or branch key. In a review, name any rendered expression that
captures outer target state and
recommend using the lambda target there. If a test must prove transition
identity, check outgoing and incoming content during the overlap; checking
only the settled destination misses a shared-identity bug. Read
AnimatedContent identity for state-holder
details.State in layout or draw block modifiers when it changes at frame rate; route deeper diagnosis to Compose performance.| 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.