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

Android Jetpack Compose:如何设置可展开列表仅展开单个列表项

Jetpack Compose 实现列表项点击展开/收起互斥效果

要实现点击卡片仅展开对应列表项、点击其他卡片时收起当前项并展开新项的效果,核心是维护一个当前展开项的唯一标识状态,通过状态控制每个列表项的展开/收起状态。下面是具体实现步骤:

  • 第一步:定义列表项数据类
    需要一个唯一ID来区分每个列表项,比如:

    data class ListItem(
        val id: Int,
        val title: String,
        val content: String
    )
    
  • 第二步:维护展开状态
    在Composable中用remember+mutableStateOf保存当前展开项的ID,初始值设为null表示无展开项:

    val expandedItemId = remember { mutableStateOf<Int?>(null) }
    
  • 第三步:构建可展开列表
    使用LazyColumn加载列表,每个列表项做可点击卡片,点击时更新状态:如果点击的是当前展开项则收起,否则展开新项。根据状态判断是否显示展开内容。

完整实现代码:

@Composable
fun ExpandableList() {
    // 模拟测试数据
    val items = remember {
        listOf(
            ListItem(1, "卡片1", "这是卡片1的详细内容,支持多行文本展示..."),
            ListItem(2, "卡片2", "这是卡片2的详细内容,包含更多自定义样式..."),
            ListItem(3, "卡片3", "这是卡片3的详细内容,可扩展为复杂布局...")
        )
    }

    val expandedItemId = remember { mutableStateOf<Int?>(null) }

    LazyColumn(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        contentPadding = PaddingValues(16.dp)
    ) {
        items(items) { item ->
            Card(
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable {
                        // 点击逻辑:切换当前项展开状态,或展开新项并收起旧项
                        expandedItemId.value = if (expandedItemId.value == item.id) null else item.id
                    },
                elevation = 4.dp
            ) {
                Column(modifier = Modifier.padding(16.dp)) {
                    // 卡片标题
                    Text(text = item.title, fontSize = 18.sp, fontWeight = FontWeight.Bold)
                    
                    // 展开内容:仅当前项ID匹配时显示
                    if (expandedItemId.value == item.id) {
                        Spacer(modifier = Modifier.height(8.dp))
                        Text(text = item.content, fontSize = 14.sp, color = Color.Gray)
                    }
                }
            }
        }
    }
}

data class ListItem(
    val id: Int,
    val title: String,
    val content: String
)

补充说明

  • 核心逻辑依赖expandedItemId的唯一性,每次点击新项时,旧展开项的ID不再匹配状态值,会自动隐藏。
  • 如果不需要点击同一卡片切换收起,只需把点击逻辑改为expandedItemId.value = item.id即可。
  • 可以根据需求自定义卡片样式、展开内容的布局,比如加入动画过渡效果(用AnimatedVisibility替代简单的if判断)。

内容的提问来源于stack exchange,提问作者Ansari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:46:03