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

Jetpack Compose:非滚动自适应网格如何自动计算可显示项数并添加自定义尾项

在Jetpack Compose中实现自适应不可滚动网格布局(含自定义“查看全部”项)

要实现根据屏幕/容器尺寸自动适配项数的不可滚动网格,核心思路是先计算可用空间能容纳的总项数(预留一个位置给“查看全部”),再截取对应数量的参与者项,最后用非懒加载布局实现网格。以下是具体实现方案:

核心步骤

  1. 获取布局可用的宽高尺寸
  2. 计算网格列数(和你之前用的GridCells.Adaptive(120.dp)逻辑保持一致)
  3. 根据项的固定高度计算可容纳的行数,进而得到可显示的参与者项数(总项数-1,留位置给“查看全部”)
  4. 截取参与者列表,结合“查看全部”项用非懒加载布局渲染

代码实现

方案一:用FlowRow(推荐,Material3自带)

FlowRow会自动根据宽度换行,天然适配不可滚动的网格场景:

BoxWithConstraints {
    val availableWidth = maxWidth
    val availableHeight = maxHeight

    // 配置参数,根据你的实际UI调整
    val minColumnWidth = 120.dp
    val horizontalSpacing = 8.dp
    val itemHeight = 140.dp // 替换为你的Audience项实际高度
    val verticalSpacing = 8.dp

    // 计算列数,和GridCells.Adaptive逻辑对齐
    val columnCount = max(1, (availableWidth + horizontalSpacing) / (minColumnWidth + horizontalSpacing)).toInt()
    // 计算可容纳的行数
    val rowCount = max(1, (availableHeight + verticalSpacing) / (itemHeight + verticalSpacing)).toInt()
    // 可显示的参与者项数(预留1个位置给“查看全部”)
    val maxParticipantCount = columnCount * rowCount - 1

    val participants = viewModel.state.value.participantsShown
    val participantsToShow = participants.take(maxParticipantCount)

    FlowRow(
        horizontalArrangement = Arrangement.spacedBy(horizontalSpacing),
        verticalArrangement = Arrangement.spacedBy(verticalSpacing),
        modifier = Modifier.fillMaxSize()
    ) {
        // 渲染截取的参与者项
        participantsToShow.forEach { participant ->
            Audience(
                participant = participant,
                modifier = Modifier.width(minColumnWidth).height(itemHeight)
            )
        }
        // 渲染“查看全部”项
        OpenAllParticipants(
            viewModel = viewModel,
            modifier = Modifier.width(minColumnWidth).height(itemHeight)
        )
    }
}

方案二:用LazyVerticalGrid(限制高度实现不可滚动)

如果坚持用LazyVerticalGrid,需要手动限制其高度,让它刚好容纳所有项:

BoxWithConstraints {
    val availableWidth = maxWidth
    val availableHeight = maxHeight

    // 同方案一的配置参数
    val minColumnWidth = 120.dp
    val horizontalSpacing = 8.dp
    val itemHeight = 140.dp
    val verticalSpacing = 8.dp

    val columnCount = max(1, (availableWidth + horizontalSpacing) / (minColumnWidth + horizontalSpacing)).toInt()
    val rowCount = max(1, (availableHeight + verticalSpacing) / (itemHeight + verticalSpacing)).toInt()
    val maxParticipantCount = columnCount * rowCount - 1

    val participants = viewModel.state.value.participantsShown
    val participantsToShow = participants.take(maxParticipantCount)

    // 计算网格总高度,限制LazyVerticalGrid高度使其不可滚动
    val gridTotalHeight = (itemHeight + verticalSpacing) * rowCount - verticalSpacing

    LazyVerticalGrid(
        verticalArrangement = Arrangement.spacedBy(verticalSpacing),
        horizontalArrangement = Arrangement.spacedBy(horizontalSpacing),
        columns = GridCells.Adaptive(minColumnWidth),
        modifier = Modifier.height(gridTotalHeight)
    ) {
        items(participantsToShow) { participant ->
            Audience(participant = participant)
        }
        item {
            OpenAllParticipants(viewModel = viewModel)
        }
    }
}

注意事项

  • 如果你的Audience项高度是动态的(比如根据内容变化),可以先用Modifier.onSizeChanged测量一个项的实际高度,再用mutableStateOf保存高度值,后续计算行数时使用这个实际高度。
  • 极端场景处理:当屏幕极小导致maxParticipantCount为0时,只会显示“查看全部”项,确保UI不会异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 18:45:36