在 Jetpack Compose 中,Crossfade 是一个专为不同内容或布局之间的交叉淡入淡出(Cross-fade)切换设计的轻量级动画 API。
当你的界面需要在两个(或多个)不同的 Composable 状态之间切换,并且希望旧内容淡出、新内容淡入时,Crossfade 可以用极少的代码实现极其平滑的视觉过渡。
一、 核心作用与特点
- 内容平滑交叉淡入淡出
它会自动处理旧内容的淡出(Alpha 从 1 降到 0)和新内容的淡入(Alpha 从 0 升到 1),两者的切换是同时进行且无缝衔接的。 - 基于状态 Key 的驱动
你只需传入一个目标状态(比如一个枚举值、布尔值或整型 ID)。当这个 Key 发生变化时,Crossfade 会自动触发内部的淡入淡出动画。 - 替代复杂的手动 Visibility 控制
相比于写多个 AnimatedVisibility 去控制互斥显示,Crossfade 专门针对"二选一"或"多选一"的内容替换场景进行了封装,代码更加简洁。
二、 典型使用示例
以下代码展示了如何使用 Crossfade 实现底部 Tab 切换或视图状态切换(例如在"首页"和"个人中心"之间切换):
enum class ScreenType {
Home, Profile
}
@Composable
fun CrossfadeDemo() {
// 1. 定义控制当前显示内容的视图状态
var currentScreen by remember { mutableStateOf(ScreenType.Home) }
Column(
modifier = Modifier.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
// 切换按钮
Row(modifier = Modifier.padding(bottom = 16.dp)) {
Button(onClick = { currentScreen = ScreenType.Home }) {
Text("首页")
}
Spacer(modifier = Modifier.width(8.dp))
Button(onClick = { currentScreen = ScreenType.Profile }) {
Text("个人中心")
}
}
// 2. 使用 Crossfade 包裹内容切换区域
Crossfade(
targetState = currentScreen,
animationSpec = tween(durationMillis = 400),
label = "ScreenCrossfade"
) { screen ->
// 3. 根据不同的 targetState 渲染对应的 UI
when (screen) {
ScreenType.Home -> {
Box(
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
.background(Color.Blue, RoundedCornerShape(8.dp)),
contentAlignment = Alignment.Center
) {
Text("🏠 欢迎来到首页内容", color = Color.White, fontSize = 18.sp)
}
}
ScreenType.Profile -> {
Box(
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
.background(Color.Magenta, RoundedCornerShape(8.dp)),
contentAlignment = Alignment.Center
) {
Text("👤 个人中心与设置页面", color = Color.White, fontSize = 18.sp)
}
}
}
}
}
}