Jetpack Compose中AnimatedVisibility搭配SwipeToDismiss新增项入场动画不触发
问题原因
- AnimatedVisibility初始状态问题:你当前把
AnimatedVisibility的visible参数仅和删除状态isDismissed绑定,新增列表项时,新生成的item的rememberDismissState默认isDismissed为false,所以AnimatedVisibility初始化时visible就是true,直接渲染为可见状态,不会触发enter动画。 - 删除逻辑硬编码delay不是最优解:硬编码300ms延迟依赖动画时长硬匹配,后续如果改动画时长还要同步改delay值,容易出问题。
修复方案
1. 新增item入场动画修复
你可以直接使用Compose LazyColumn官方提供的item动画API,不需要在每个item内部套AnimatedVisibility来处理入场,只需要给每个item加animateItemPlacement修饰符,同时保留原有AnimatedVisibility处理删除的退出动画即可,调整后代码如下:
@Composable fun DisplayTasks( tasks: List<ToDoTask>, onSwipeToDelete: (Action, ToDoTask) -> Unit, navigateToTaskScreen: (Int) -> Unit ) { LazyColumn { items( items = tasks, key = { task -> task.id } ) { task -> val dismissState = rememberDismissState() val dismissDirection = dismissState.dismissDirection val isDismissed = dismissState.isDismissed(DismissDirection.EndToStart) // 用LaunchedEffect替代手动创建协程作用域,性能更稳定 LaunchedEffect(isDismissed) { if (isDismissed && dismissDirection == DismissDirection.EndToStart) { delay(300) onSwipeToDelete(Action.DELETE, task) } } AnimatedVisibility( visible = !isDismissed, exit = shrinkVertically( animationSpec = tween( durationMillis = 300, ) ), // 新增animateItemPlacement处理新增/排序的入场/位移动画 modifier = Modifier.animateItemPlacement( animationSpec = tween(durationMillis = 300) ) ) { SwipeToDismiss( state = dismissState, directions = setOf(DismissDirection.EndToStart), dismissThresholds = { FractionalThreshold(0.2f) }, background = { RedBackground() }, dismissContent = { LazyColumnItem( toDoTask = task, navigateToTaskScreen = navigateToTaskScreen ) } ) } } } }
2. 删除逻辑delay优化(可选)
如果你不想硬编码delay,可以监听AnimatedVisibility的动画结束回调来触发删除操作,调整后不需要再写LaunchedEffect的delay逻辑:
AnimatedVisibility( visible = !isDismissed, exit = shrinkVertically(tween(300)), modifier = Modifier.animateItemPlacement(tween(300)), // 退出动画执行完成后自动触发删除逻辑,无需硬编码延迟时长 onExitFinished = { onSwipeToDelete(Action.DELETE, task) } ) { // 原有SwipeToDismiss内容不变 }
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

