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

Jetpack Compose中嵌套LazyRow滚动不流畅问题求助

Jetpack Compose LazyColumn嵌套LazyRow滚动不流畅问题修复

问题诊断

你遇到的滚动卡顿、反向滚动中途停止的问题,核心原因有两个:

  • 嵌套滚动事件冲突:父容器LazyColumn的手势处理逻辑会干扰子LazyRow的横向滚动,尤其是反向滑动时,手势识别冲突导致滚动中断。
  • 冗余渲染拖垮性能:每个LazyColumn列表项中的LazyRow都遍历了整个uiState.orders数据源,导致每行都重复渲染所有订单,既浪费资源,也会破坏滚动时的状态稳定性。

修复方案

1. 处理嵌套滚动冲突

给子LazyRow添加nestedScroll修饰符,明确让它优先捕获横向滚动事件,避免父容器干扰。

2. 优化数据源渲染

每个LazyRow只渲染与当前LazyColumn项相关的订单(而非全部订单),减少冗余渲染。

3. 绑定独立滚动状态

给每个LazyRow分配独立的LazyListState,避免多个横向滚动容器共享状态引发异常。

修复后的代码

val lazyColumnState = rememberLazyListState()
Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
    if (uiState.isLoading)
        CircularProgressIndicator()
    else
        Column(modifier = modifier.fillMaxSize()) {
            // 顶部标题行保留原逻辑
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .height(48.dp),
                horizontalArrangement = Arrangement.spacedBy(4.dp)
            ) {
                Box(
                    modifier = Modifier
                        .fillMaxHeight()
                        .width(60.dp)
                        .padding(horizontal = 8.dp),
                    contentAlignment = Alignment.TopEnd
                ) {
                    MediumContentText(
                        text = stringResource(R.string.time),
                        style = MaterialTheme.typography.bodyLarge.copy(
                            color = MaterialTheme.colorScheme.outline,
                            fontSize = 12.sp
                        ),
                    )
                }
                VerticalDivider(
                    modifier = Modifier
                        .fillMaxHeight()
                )
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(horizontal = 16.dp),
                    horizontalArrangement = Arrangement.Start,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Column(
                        modifier = Modifier.fillMaxWidth(),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.Start
                    ) {
                        MediumContentText(
                            text = stringResource(R.string.schedule),
                            style = MaterialTheme.typography.bodyLarge.copy(
                                color = MaterialTheme.colorScheme.outline,
                                fontSize = 12.sp
                            ),
                        )
                    }
                }
            }
            HorizontalDivider()
            LazyColumn(
                state = lazyColumnState,
                modifier = Modifier.fillMaxHeight(),
            ) {
                itemsIndexed(uiState.orders ?: emptyList()) { _, columnItem ->
                    val startTime = columnItem?.visitAt.convertToTimeZone()
                    val endTime = columnItem?.visitAt.addHours(3)
                    
                    // 为每个LazyRow创建独立滚动状态
                    val lazyRowState = rememberLazyListState()
                    // 按需过滤当前行需展示的订单,示例为匹配当前项ID,可根据业务调整过滤逻辑
                    val rowItems = uiState.orders?.filter { it?.id == columnItem?.id } ?: emptyList()

                    Row(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(160.dp),
                        horizontalArrangement = Arrangement.spacedBy(4.dp)
                    ) {
                        Column(
                            modifier = Modifier
                                .width(60.dp)
                                .fillMaxHeight()
                                .padding(10.dp),
                            verticalArrangement = Arrangement.Top,
                            horizontalAlignment = Alignment.CenterHorizontally
                        ) {
                            startTime?.let {
                                MediumContentText(
                                    text = "${it.time.hour}:${it.time.minute}".formatTimeWithTwoNumber(),
                                )
                            }
                            Spacer(modifier = Modifier.height(8.dp))
                            endTime?.let {
                                MediumContentText(
                                    text = "${it.time.hour}:${it.time.minute}".formatTimeWithTwoNumber(),
                                    style = TextStyle(
                                        color = MaterialTheme.colorScheme.outline,
                                        fontSize = 12.sp
                                    )
                                )
                            }
                        }

                        VerticalDivider(
                            modifier = Modifier
                                .fillMaxHeight()
                        )

                        LazyRow(
                            state = lazyRowState,
                            modifier = Modifier
                                .fillMaxWidth()
                                .height(160.dp)
                                .padding(vertical = 4.dp)
                                // 添加嵌套滚动处理,优先响应横向滚动
                                .nestedScroll(rememberScrollableState { 0f }),
                            horizontalArrangement = Arrangement.spacedBy(8.dp),
                            contentPadding = PaddingValues(4.dp)
                        ) {
                            items(rowItems) { rowItem ->
                                Surface(
                                    modifier = Modifier.width(250.dp),
                                    shape = RoundedCornerShape(16.dp),
                                    shadowElevation = 8.dp,
                                    color = if (rowItem?.status == "done" || rowItem?.status == "cancel") 
                                        MaterialTheme.colorScheme.secondary else MaterialTheme.colorScheme.surface
                                ) {
                                    ScheduleRow(
                                        item = rowItem,
                                        onClick = { onNavigateToDetail(rowItem) }
                                    )
                                }
                            }
                        }
                    }
                    HorizontalDivider()
                }
            }
        }
}

关键修复点说明

  • nestedScroll修饰符:通过rememberScrollableState { 0f }让LazyRow优先捕获横向滚动手势,避免父LazyColumn的逻辑干扰反向滚动。
  • 独立滚动状态:每个LazyRow使用rememberLazyListState()创建专属状态,防止多个横向滚动容器互相影响。
  • 数据源过滤:只渲染当前行所需的订单数据,大幅减少冗余渲染,提升滚动流畅度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 03:24:55