一、基础动画实现
1. 渐显/渐隐动画
var visible by remember { mutableStateOf(true) }
val alpha by animateFloatAsState(
targetValue = if (visible) 1f else 0f,
animationSpec = tween(durationMillis = 300)
)
Box(
Modifier
.alpha(alpha)
.background(Color.Blue)
.size(100.dp)
)
2. 尺寸变化动画
var expanded by remember { mutableStateOf(false) }
val size by animateDpAsState(
targetValue = if (expanded) 200.dp else 100.dp,
animationSpec = spring(stiffness = Spring.StiffnessLow)
)
Box(
Modifier
.size(size)
.background(MaterialTheme.colors.primary)
.clickable { expanded = !expanded }
)
二、过渡动画
1. 多属性组合动画
val transition = updateTransition(targetState = expanded)
val size by transition.animateDp { if (it) 200.dp else 100.dp }
val color by transition.animateColor { if (it) Color.Red else Color.Blue }
Box(
Modifier
.size(size)
.background(color)
)
2. 可见性动画
var visible by remember { mutableStateOf(true) }
AnimatedVisibility(
visible = visible,
enter = fadeIn() + expandVertically(),
exit = shrinkHorizontally() + fadeOut()
) {
Box(Modifier.size(100.dp).background(Color.Green))
}
三、手势驱动动画
拖动释放动画
val offset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) }
Box(
Modifier
.offset { offset.value.toIntOffset() }
.pointerInput(Unit) {
detectDragGestures { _, dragAmount ->
launch {
offset.snapTo(offset.value + dragAmount)
}
}
}
.size(100.dp)
.background(Color.Magenta)
)
四、高级动画技巧
1. 无限循环动画
val infiniteTransition = rememberInfiniteTransition()
val scale by infiniteTransition.animateFloat(
initialValue = 1f,
targetValue = 1.5f,
animationSpec = infiniteRepeatable(
animation = tween(1000),
repeatMode = RepeatMode.Reverse
)
)
Box(
Modifier
.size(100.dp)
.graphicsLayer(scaleX = scale, scaleY = scale)
.background(Color.Cyan)
)
2. 矢量路径动画
val path = Path().apply {
moveTo(100f, 100f)
quadraticTo(300f, 200f, 500f, 100f)
}
val animatable = remember { Animatable(0f, Float.VectorConverter) }
LaunchedEffect(Unit) {
animatable.animateTo(1f, animationSpec = tween(2000))
}
Box(
Modifier
.graphicsLayer {
val point = path.getPoint(animatable.value)
translationX = point.x
translationY = point.y
}
.size(50.dp)
.background(Color.Yellow)
)
五、最佳实践
-
性能优化:
- 优先使用
remember
缓存动画对象 - 对复杂动画使用
derivedStateOf
- 避免在动画过程中触发重组
- 优先使用
-
动画协调:
val transition = updateTransition(checked)
val borderWidth by transition.animateDp { if (it) 4.dp else 2.dp }
val elevation by transition.animateDp { if (it) 8.dp else 2.dp }
Surface(
modifier = Modifier
.border(borderWidth, Color.Red, CircleShape)
.elevation(elevation),
shape = CircleShape
) { /* ... */ }
六、调试工具
- 使用
Modifier.drawWithContent { }
可视化动画进度 - 开启布局检查器查看动画参数实时变化
- 使用
debugInspectorInfo
添加调试信息
Jetpack Compose 的声明式动画系统通过智能重组机制,可以自动处理动画的生命周期和状态管理。