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

点击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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:37:04