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

Jetpack Compose中如何高效实现带动画的数千项可折叠网格分区

解决LazyVerticalGrid分区折叠动画的性能优化方案

针对你在单个LazyVerticalGrid中实现带动画的分区折叠功能时遇到的性能问题,这里提供几个高效的优化方案,既保留单网格的性能优势,又能实现流畅的折叠动画:

1. 缩小AnimatedVisibility的作用范围

不要给每个列表项单独添加AnimatedVisibility,而是将整个分区的条目块用AnimatedVisibility包裹,同时手动处理分区间距替代原有的verticalArrangement,减少动画节点数量:

LazyVerticalGrid(
    modifier = Modifier.fillMaxSize().padding(horizontal = 10.dp),
    columns = GridCells.Fixed(5),
) {
    viewState.sections.forEach { section ->
        // 分区标题(跨列)
        item(span = { GridItemSpan(maxLineSpan) }) {
            InventorySectionHeader(section = section, intent = intent)
        }

        // 用AnimatedVisibility包裹整个分区的条目集合
        AnimatedVisibility(
            visible = !section.collapsed,
            enter = expandVertically(expandFrom = Alignment.Top) + fadeIn(),
            exit = shrinkVertically(shrinkTowards = Alignment.Top) + fadeOut(),
            modifier = Modifier.animateContentSize()
        ) {
            items(items = section.items, key = { it.id }) { item ->
                InventorySectionItem(item = item, intent = intent)
            }
        }

        // 手动添加分区间的间距,避免原verticalArrangement导致的空空间问题
        if (viewState.sections.last() != section) {
            item(span = { GridItemSpan(maxLineSpan) }) {
                Spacer(modifier = Modifier.height(20.dp))
            }
        }
    }
}

这种方式将动画范围从单个item提升到整个分区条目集合,大幅减少Compose动画节点的数量,直接缓解性能衰减问题。

2. 优化重组逻辑,减少不必要的计算

通过remember缓存展开状态,并同步外部viewState的变化,避免频繁的重组:

LazyVerticalGrid(
    modifier = Modifier.fillMaxSize().padding(horizontal = 10.dp),
    columns = GridCells.Fixed(5),
) {
    viewState.sections.forEach { section ->
        // 用remember缓存展开状态,减少不必要的重组
        val isExpanded = remember { mutableStateOf(!section.collapsed) }
        
        // 同步viewState的外部状态变化
        LaunchedEffect(section.collapsed) {
            isExpanded.value = !section.collapsed
        }

        // 标题点击切换展开状态
        item(span = { GridItemSpan(maxLineSpan) }) {
            InventorySectionHeader(
                section = section,
                intent = intent,
                onToggle = { isExpanded.value = !isExpanded.value }
            )
        }

        AnimatedVisibility(
            visible = isExpanded.value,
            enter = expandVertically(expandFrom = Alignment.Top) + fadeIn(),
            exit = shrinkVertically(shrinkTowards = Alignment.Top) + fadeOut(),
            modifier = Modifier.animateContentSize()
        ) {
            items(items = section.items, key = { it.id }) { item ->
                InventorySectionItem(item = item, intent = intent)
            }
        }

        // 分区间距处理
        if (viewState.sections.last() != section) {
            item(span = { GridItemSpan(maxLineSpan) }) {
                Spacer(modifier = Modifier.height(20.dp))
            }
        }
    }
}

3. 额外性能优化技巧

  • 确保InventorySectionItem的参数都是稳定类型(如data class),避免无意义的重组;
  • 提前在viewState中完成所有数据过滤、排序等计算,不要在Composable函数或LazyGrid的items块中做复杂逻辑;
  • 调整动画的animationSpec,适当缩短动画时长(比如用spring(stiffness = Spring.StiffnessMedium)),减少动画期间的性能消耗。

这些方案既保留了单个LazyVerticalGrid的高性能加载优势,又能实现流畅的分区折叠动画,无需切换到多网格的低性能方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 20:03:09