You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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)
            )
        }
    }
}

代码说明

  1. 动画状态管理:用mutableStateListOf记录每个列表项的动画进度,确保状态变化能触发重组
  2. 动画值计算:
    • alpha:通过animateFloatAsState实现从0到1的淡入效果
    • offsetY:实现从-200dp位置下落至原位置的位移动画
  3. 延迟触发:利用LaunchedEffect在每个列表项进入组合后,根据索引添加延迟,实现依次入场的效果
  4. 动画参数匹配:动画时长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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 23:44:50