点击LazyColumn元素实现单卡片展开折叠功能异常求助
解决LazyColumn中卡片展开/折叠不同步的问题
问题根源
你的实现存在状态双源不一致的问题:父组件通过expandedProbeId管理全局唯一的展开卡片ID,但子组件Probe自己维护了一个rememberSaveable的expState。这个内部状态只会在组件初始化时读取父组件的isExpanded参数,后续父组件状态变化时,子组件不会自动同步,只有页面重建(切换页面返回)时才会重新初始化,导致功能延迟生效。
修复方案
去掉子组件内部的独立状态,完全依赖父组件传递的isExpanded控制显示逻辑,点击事件直接通知父组件更新全局状态:
修改后的父组件代码
val expandedProbeId = remember { mutableStateOf(-1) } LazyColumn() { items( items = probeList, key = { item: Probe -> item.id } ) { probe -> Probe( probe = probe, isExpanded = expandedProbeId.value == probe.id, onToggleExpand = { // 点击时切换:当前展开就折叠,否则展开当前卡片 expandedProbeId.value = if (expandedProbeId.value == probe.id) -1 else probe.id } ) } }
修改后的Probe组件代码
@Composable fun Probe( probe: Probe, isExpanded: Boolean, onToggleExpand: () -> Unit ) { val temperatureFontSizeState: Int by animateIntAsState( targetValue = if (isExpanded) 32 else 15, animationSpec = tween(300), label = "temperatureFontSize" ) Card( modifier = Modifier .fillMaxWidth() .wrapContentHeight() .padding(4.dp) .clickable { onToggleExpand() } ) { Column(verticalArrangement = Arrangement.SpaceBetween) { Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 24.dp, vertical = 18.dp), verticalAlignment = Alignment.Top, horizontalArrangement = Arrangement.SpaceBetween ) { Text( text = probe.temperature.toString(), fontSize = temperatureFontSizeState.sp ) Text(text = convertTimestampToDateTime(probe.timeStamp)) } val enterAnim = remember { fadeIn(tween(300, easing = FastOutLinearInEasing)) + expandVertically(tween(300)) } val exitAnim = remember { fadeOut(tween(300, easing = FastOutLinearInEasing)) + shrinkVertically(tween(300)) } AnimatedVisibility( visible = isExpanded, enter = enterAnim, exit = exitAnim, modifier = Modifier.fillMaxWidth() ) { Column { Row( modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp), verticalAlignment = Alignment.Top ) { Text("Description:") } Row( modifier = Modifier .fillMaxWidth() .padding(horizontal = 24.dp, vertical = 9.dp), verticalAlignment = Alignment.Top, horizontalArrangement = Arrangement.SpaceBetween ) { Text(probe.descr) } } } } } }
关键修改点
- 移除
Probe内部的expState,所有状态逻辑统一由父组件的expandedProbeId管理 - 点击事件改为
onToggleExpand,直接让父组件负责切换展开/折叠状态,确保全局唯一展开卡片 - 动画和可见性判断直接绑定父组件传入的
isExpanded,状态变化时立即响应
内容的提问来源于stack exchange,提问作者STregg
相关产品推荐
相关产品推荐

