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
相关产品推荐
相关产品推荐

