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

如何在Jetpack Compose中实现分区滚动切换的分类表单效果?

组件标准名称

你描述的这类互斥展开的分组交互组件通用标准名称为 手风琴(Accordion)组件,用在表单场景下也可称为手风琴表单,完全符合你提到的「仅单个分组展开、其余分组头部可见、支持点击/滚动切换展开项」的交互特征。

Jetpack Compose 实现方向
  • 基础容器选型:优先用LazyColumn承载全部分组,天然支持滚动能力,每个分组对应一个LazyColumn子项
  • 互斥状态管理:通过mutableStateOf<Int>存储当前展开的分组索引,更新状态时全局仅一个分组处于展开状态
  • 分组UI实现:每个分组由固定显示的头部栏、可折叠的输入框内容区两部分组成,内容区用AnimatedVisibility包裹可实现顺滑的展开收起动画,贴近垂直ViewPager的切换效果
  • 交互联动实现:
    • 点击分组头部时直接更新展开索引,同时调用lazyListState.animateScrollToItem()让对应分组滚动到合适位置
    • 如需滚动时自动切换展开项,可监听LazyListState的滚动状态,判断当前可视区域内占比最高的分组,自动更新展开索引
  • 输入状态保活:建议将所有输入框的文本状态提升至ViewModel层,避免分组折叠/展开切换时输入内容丢失

核心实现示例

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch

// 表单分组数据结构
data class FormGroup(val groupName: String, val inputFields: List<String>)

@Composable
fun ExclusiveAccordionForm(formGroups: List<FormGroup>) {
    val lazyListState = rememberLazyListState()
    val coroutineScope = rememberCoroutineScope()
    // 默认展开第一个分组
    var expandedIndex by remember { mutableStateOf(0) }

    LazyColumn(state = lazyListState, modifier = Modifier.fillMaxWidth()) {
        itemsIndexed(formGroups) { index, group ->
            Column(modifier = Modifier.fillMaxWidth()) {
                // 分组头部,点击切换展开状态并滚动到对应位置
                Text(
                    text = group.groupName,
                    fontSize = 18.sp,
                    modifier = Modifier
                        .fillMaxWidth()
                        .clickable {
                            expandedIndex = index
                            coroutineScope.launch {
                                lazyListState.animateScrollToItem(index)
                            }
                        }
                        .padding(16.dp)
                )
                // 输入框内容区,仅当前选中分组展开
                AnimatedVisibility(visible = expandedIndex == index) {
                    Column(modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)) {
                        group.inputFields.forEach { fieldLabel ->
                            OutlinedTextField(
                                value = "", // 实际使用时替换为ViewModel中存储的状态
                                onValueChange = { /* 更新ViewModel中的对应状态 */ },
                                label = { Text(fieldLabel) },
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(vertical = 8.dp)
                            )
                        }
                    }
                }
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 12:27:04