Jetpack Compose LazyColumn侧滑删除动画结束不流畅问题求助
解决Jetpack Compose LazyColumn滑动删除时卡片跳位问题
问题分析
你遇到的问题确实和LazyColumn的Arrangement.spacedBy(32.dp)有关。spacedBy的间距由LazyColumn统一管理,当你用AnimatedVisibility收缩删除的卡片时,间距并不会跟着动画消失——只有当数据从列表中移除后,LazyColumn才会瞬间移除对应的间距,这就导致了下方卡片突然跳位的现象。
要保留卡片间距同时解决动画问题,需要把间距从LazyColumn的全局设置转移到每个列表项的本地容器中,让间距和卡片一起参与动画。
修复步骤
- 移除LazyColumn的全局间距设置,删除
verticalArrangement = Arrangement.spacedBy(32.dp) - 给每个列表项添加本地间距,在
SwipeToDeleteContainer内部给卡片包裹带底部间距的容器(最后一个item不加,避免多余间距) - 调整动画范围,确保动画作用于包含间距的整个容器,而非仅卡片本身
修改后的代码
MainScreen.kt
修改LazyColumn部分,移除全局间距并改用itemsIndexed传递索引:
LazyColumn( contentPadding = PaddingValues(bottom = 10.dp, top = 10.dp), // 移除verticalArrangement = Arrangement.spacedBy(32.dp) modifier = Modifier.weight(10f) ) { itemsIndexed( items = state.tasks, key = { _, task -> task.id } ) { index, task -> SwipeToDeleteContainer( item = task, onDelete = { onEvent(TaskEvent.DeleteTask(task.id)) }, isLastItem = index == state.tasks.lastIndex ) { TaskCard( taskCardDto = task, onCheckedChange = { id, done -> onEvent(TaskEvent.SetDone(id, done)) } ) } } }
SwipeToDeleteContainer.kt
更新容器逻辑,添加间距参数并包裹带间距的容器:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun <T> SwipeToDeleteContainer( item: T, onDelete: (T) -> Unit, animationDuration: Int = 500, isLastItem: Boolean = false, // 新增参数:判断是否为最后一项 content: @Composable (T) -> Unit ) { var isRemoved by remember { mutableStateOf(false) } val state = rememberDismissState( confirmValueChange = { value -> if (value == DismissValue.DismissedToStart) { isRemoved = true true } else { false } } ) LaunchedEffect(key1 = isRemoved) { if(isRemoved) { delay(animationDuration.toLong()) onDelete(item) } } AnimatedVisibility( visible = !isRemoved, exit = shrinkVertically( animationSpec = tween(durationMillis = animationDuration), shrinkTowards = Alignment.Top ) + fadeOut() ) { // 包裹带间距的容器,最后一项不加底部间距 Box(modifier = Modifier.padding(bottom = if (isLastItem) 0.dp else 32.dp)) { SwipeToDismiss( state = state, background = { DeleteBackground(swipeDismissState = state) }, dismissContent = { content(item) }, directions = setOf(DismissDirection.EndToStart) ) } } }
TaskCard.kt & Constants.kt
这两个文件无需修改,保持原有逻辑即可。
原理说明
通过将间距从LazyColumn的全局设置转移到每个列表项的本地容器,删除动画时卡片和间距会一起收缩消失,LazyColumn的布局会平滑过渡,不会出现跳位现象。itemsIndexed用于判断最后一项,避免列表底部出现多余的间距。
内容的提问来源于stack exchange,提问作者pochopsp
相关产品推荐
相关产品推荐

