如何为Jetpack Compose LazyList添加入场动画?复刻RecyclerView下落动画
在Jetpack Compose中实现LazyList列表项的下落入场动画
完全可以在Jetpack Compose中实现类似RecyclerView的"Fall down"下落入场动画,以下是基于你现有代码的实现方案:
核心思路
对应原RecyclerView实现中的动画逻辑:
- 每个列表项从上方(-200%位置)下落至原位置
- 伴随从透明到完全显示的淡入效果
- 列表项按顺序依次入场,延迟为动画时长的15%(300ms × 15% = 45ms)
实现代码
修改你的FoodCategoriesScreen组件,添加动画逻辑:
@Composable fun FoodCategoriesScreen() { val items = listOf("Starters", "Mains", "Desserts") // 记录每个列表项的动画完成进度,0=未开始,1=完成 val animationProgresses = remember(items.size) { mutableStateListOf(*Array(items.size) { 0f }) } LazyColumn { itemsIndexed(items) { index, item -> // 透明度动画:从0到1 val alpha by animateFloatAsState( targetValue = animationProgresses[index], animationSpec = tween(durationMillis = 300), label = "alpha_animation_$index" ) // Y轴偏移动画:从-200dp到0 val offsetY by animateFloatAsState( targetValue = if (animationProgresses[index] == 1f) 0f else -200.dp.toPx(), animationSpec = tween(durationMillis = 300), label = "offsetY_animation_$index" ) // 当组件进入组合时,按索引延迟触发动画 LaunchedEffect(index) { delay(index * 45L) // 对应原layoutAnimation的15%延迟 animationProgresses[index] = 1f } Text( text = item, modifier = Modifier .padding(16.dp) .alpha(alpha) .offset(y = offsetY) ) } } }
代码说明
- 动画状态管理:用
mutableStateListOf记录每个列表项的动画进度,确保状态变化能触发重组 - 动画值计算:
alpha:通过animateFloatAsState实现从0到1的淡入效果offsetY:实现从-200dp位置下落至原位置的位移动画
- 延迟触发:利用
LaunchedEffect在每个列表项进入组合后,根据索引添加延迟,实现依次入场的效果 - 动画参数匹配:动画时长300ms,延迟45ms(300ms×15%),完全对应原RecyclerView的动画配置
另一种简化实现(使用AnimatedVisibility)
如果你更倾向于用Compose的AnimatedVisibility组件,也可以这样写:
@Composable fun FoodCategoriesScreen() { val items = listOf("Starters", "Mains", "Desserts") // 定义入场动画:从上方2倍自身高度位置滑入 + 淡入 val enterAnim = remember { slideInVertically(initialOffsetY = { -it * 2 }) + fadeIn() } // 记录每个列表项是否已显示 val itemVisibleStates = remember(items.size) { mutableStateListOf(*Array(items.size) { false }) } LazyColumn { itemsIndexed(items) { index, item -> LaunchedEffect(index) { delay(index * 45L) itemVisibleStates[index] = true } AnimatedVisibility( visible = itemVisibleStates[index], enter = enterAnim, exit = remember { fadeOut() } ) { Text(text = item, modifier = Modifier.padding(16.dp)) } } } }
内容的提问来源于stack exchange,提问作者wbk727
相关产品推荐
相关产品推荐

