Jetpack Compose中如何实现多个LazyColumn同步滚动
多LazyColumn同步滚动实现方法
核心逻辑非常直接:所有需要同步滚动的LazyColumn,必须共用同一个LazyListState实例,不要给每个列单独创建独立的滚动状态。
前置问题修正
你当前的代码有两个会导致同步失效/错位的问题,需要先修复:
- 各列条目高度不匹配:第一列时间条目高度为50dp,右侧数据列单条目高度为30dp,且第一列条目总数是右侧列的1/2,总高度不对齐会直接导致滚动错位,需要先把对应行的高度、总滚动高度调整为一致。
- 不要在item渲染逻辑里直接修改外部状态:原代码在Column的lambda里直接调用
stateCal.add(Calendar.MINUTE, 30),这类副作用会随列表重组反复触发,导致时间显示完全错乱,应该根据item索引直接计算对应时间,不要在渲染过程中修改全局状态。
具体实现步骤
- 在最外层Composable作用域中,仅调用一次
rememberLazyListState()创建共享的滚动状态实例 - 给所有内部的LazyColumn都传入这个共享状态作为
state参数 - 对齐各列的条目高度、总滚动高度
修正后的可运行代码
@Composable fun TableScreen2(list: List<Time>, cal: Calendar, df: DateFormat) { // 仅创建一次共享滚动状态,所有LazyColumn共用 val sharedColumnScrollState = rememberLazyListState() LazyRow(Modifier.fillMaxSize()) { item { LazyColumn( modifier = Modifier.fillParentMaxHeight(), state = sharedColumnScrollState // 传入共享状态 ) { // 对齐高度:右侧每2个30dp条目总高60dp,时间列单条目高度也设为60dp,和右侧两行对齐 items(count = list.first().timeList.size / 2) { index -> // 根据索引计算时间,不要在渲染时修改原始cal状态 val timeCal = cal.clone() as Calendar timeCal.add(Calendar.MINUTE, 30 * index) Column( modifier = Modifier .width(60.dp) .height(60.dp), verticalArrangement = Arrangement.Center ) { Text(df.format(timeCal.time)) } } } } items(4) { listIndex -> LazyColumn( modifier = Modifier.fillParentMaxHeight(), state = sharedColumnScrollState // 传入同一个共享状态 ) { itemsIndexed(list[listIndex].timeList) { timeIndex, timeItem -> Box( modifier = Modifier .height(30.dp) .width(60.dp) .background(Color.Gray), contentAlignment = Alignment.Center ) { Text(text = "$timeIndex") } } } } } }
效果演示

内容的提问来源于stack exchange,提问作者DaeWon Kwon
相关产品推荐
相关产品推荐

