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

在Jetpack Compose中实现垂直网格视图的宽度适配问题

Compose FlowRow卡片宽度适配问题

我的代码

@Composable
fun VerticalImageCards(toolsList: List<HealthTool>) {
    val domainName = stringResource(id = R.string.media_url)

    FlowRow(mainAxisSpacing = 8.dp,
        crossAxisSpacing = 16.dp,
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 16.dp),
        mainAxisSize = SizeMode.Wrap) {
        for (i in toolsList) {
            val imgUrl = "$domainName${i.url}"
            ToolsCardLayout(cardTitle = i.title, imgUrl = imgUrl)
        }
    }
}
@Composable
fun ToolsCardLayout(
    imgUrl: String,
    cardTitle: String,
) {
    Box(modifier = Modifier.clickable {}) {
        AsyncImage(model = imgUrl,
            contentDescription = null,
            contentScale = ContentScale.Crop,
            modifier = Modifier.fillMaxWidth())
        Box(modifier = Modifier
            .size(32.dp)
            .align(Alignment.TopEnd)) {
            Image(painter = painterResource(id = R.drawable.schedule),
                contentDescription = null,
                modifier = Modifier
                    .fillMaxSize()
                    .padding(top = 8.dp, end = 8.dp),
                contentScale = ContentScale.Fit)
        }
    }
    Card(modifier = Modifier
        .height(44.dp)
        .fillMaxWidth()) {
        Text(text = cardTitle,
            style = MaterialTheme.typography.h6,
            modifier = Modifier
                .padding(horizontal = 16.dp, vertical = 8.dp)
                .clip(RoundedCornerShape(bottomStart = 8.dp, bottomEnd = 8.dp)))
    }
}

代码说明

  • 从服务器获取包含工具图片、标题、描述的工具详情列表
  • imgUrl:工具图片的完整链接
  • cardTitle:工具名称

问题描述

Card组件会占满FlowRow的整个宽度。之前硬编码数据时,给卡片加weight(1f)可以解决该问题,但加载后端返回的数据后,这个方法不再生效。此外该网格布局用于首页,不能设置为可滚动。

解决方案

问题核心是FlowRow子项未设置宽度约束,且ToolsCardLayout内部使用fillMaxWidth()导致宽度失控,可通过以下两种方式修复:

方式1:基于权重分配宽度

修改VerticalImageCards中ToolsCardLayout的调用逻辑,为每个子项添加权重约束:

for (i in toolsList) {
    val imgUrl = "$domainName${i.url}"
    ToolsCardLayout(cardTitle = i.title, imgUrl = imgUrl)
        .modifier.weight(1f, fill = false) // fill设为false避免强制拉伸
}

同时调整ToolsCardLayout的内部布局,用Column整合图片和卡片,避免并列布局的宽度冲突:

@Composable
fun ToolsCardLayout(
    imgUrl: String,
    cardTitle: String,
) {
    Column(modifier = Modifier.clickable {}) {
        Box {
            AsyncImage(model = imgUrl,
                contentDescription = cardTitle,
                contentScale = ContentScale.Crop,
                modifier = Modifier.fillMaxWidth())
            Box(modifier = Modifier
                .size(32.dp)
                .align(Alignment.TopEnd)) {
                Image(painter = painterResource(id = R.drawable.schedule),
                    contentDescription = "日程标记",
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(top = 8.dp, end = 8.dp),
                    contentScale = ContentScale.Fit)
            }
        }
        Card(modifier = Modifier
            .height(44.dp)
            .fillMaxWidth()) {
            Text(text = cardTitle,
                style = MaterialTheme.typography.h6,
                modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp))
        }
    }
}

方式2:固定每行卡片数量

如果需要固定每行显示N个卡片,可直接计算卡片宽度:

@Composable
fun VerticalImageCards(toolsList: List<HealthTool>) {
    val domainName = stringResource(id = R.string.media_url)
    val screenWidth = LocalConfiguration.current.screenWidthDp.dp
    val cardCountPerRow = 2 // 自定义每行卡片数量
    val cardWidth = (screenWidth - (cardCountPerRow - 1) * 8.dp) / cardCountPerRow // 减去间距

    FlowRow(mainAxisSpacing = 8.dp,
        crossAxisSpacing = 16.dp,
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 16.dp),
        mainAxisSize = SizeMode.Wrap) {
        for (i in toolsList) {
            val imgUrl = "$domainName${i.url}"
            ToolsCardLayout(cardTitle = i.title, imgUrl = imgUrl)
                .modifier.width(cardWidth)
        }
    }
}

两种方式都能保证卡片宽度均匀分配,适配后端返回的任意数据量,且布局保持不可滚动状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:35:18