Jetpack Compose中如何在内容超最大高度时隐藏元素并显示展开按钮?
实现带自动展开按钮的可折叠卡片组件
你要的需求可以通过onGloballyPositioned修饰符测量内容实际高度,结合Compose的状态驱动重组来实现,完整代码如下:
@Composable fun CollapsibleCard( title: String, maxBodyHeight: Dp = 400.dp, content: @Composable () -> Unit ) { // 控制主体内容的展开/折叠状态 var isExpanded by remember { mutableStateOf(false) } // 记录主体内容的实际渲染高度 var contentActualHeight by remember { mutableStateOf(0.dp) } val density = LocalDensity.current Column( modifier = Modifier.fillMaxWidth() .background(Color.White, RoundedCornerShape(8.dp)) .padding(16.dp) ) { // 头部区域 Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Text(text = title, fontSize = 18.sp, fontWeight = FontWeight.Bold) // 仅当内容高度超过限制且未展开时显示展开按钮 if (contentActualHeight > maxBodyHeight && !isExpanded) { Button(onClick = { isExpanded = true }) { Text("Expand >>") } } // 展开状态下显示收起按钮 if (isExpanded) { Button(onClick = { isExpanded = false }) { Text("<< Collapse") } } } Spacer(modifier = Modifier.height(8.dp)) // 主体内容区域 Box( modifier = Modifier // 根据展开状态控制高度限制 .then(if (isExpanded) Modifier else Modifier.heightIn(max = maxBodyHeight)) // 测量内容实际高度 .onGloballyPositioned { coordinates -> with(density) { contentActualHeight = coordinates.size.height.toDp() } } ) { content() } } }
核心逻辑说明:
- 状态管理:用
remember+mutableStateOf维护两个关键状态,状态变化会自动触发组件重组,更新UI显示。 - 高度测量:
onGloballyPositioned会在组件布局完成后回调,获取内容的实际像素高度并转换为Dp,以此判断是否需要显示展开按钮。 - 内容控制:未展开时通过
heightIn(max = maxBodyHeight)限制主体高度,超出部分自动隐藏;展开后移除高度限制,显示全部内容。 - 按钮显示逻辑:只有当内容实际高度超过设定的最大限制且处于未展开状态时,才显示展开按钮;展开后切换为收起按钮。
使用示例:
@Composable fun TestCollapsibleCard() { // 模拟超长文本内容 val hugeContent = buildString { repeat(100) { append("这是一段用于测试的文本,用来模拟超过最大高度的主体内容。") } } CollapsibleCard(title = "测试卡片") { Text(text = hugeContent) } }
内容的提问来源于stack exchange,提问作者Horst
相关产品推荐
相关产品推荐

