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

Jetpack Compose:实现最大高度15dp的自适应图片行

Jetpack Compose 一行自适应图片实现方案

要实现一行图片最大高度15dp,屏幕宽度不足时等比例缩放适配、保持统一高度的效果,自定义Layout是最直接的解决方案,以下是具体实现:

核心思路

  1. 先计算所有图片在15dp高度下的总宽度,和屏幕宽度对比
  2. 若总宽度≤屏幕宽度:直接以15dp高度展示所有图片
  3. 若总宽度>屏幕宽度:计算缩放比例,让所有图片按比例缩小,总宽度刚好适配屏幕,同时保持统一高度

完整代码实现

@Composable
fun AdaptiveImageRow(
    modifier: Modifier = Modifier,
    maxImageHeight: Dp = 15.dp,
    imageResources: List<Int>
) {
    val density = LocalDensity.current
    val maxHeightPx = with(density) { maxImageHeight.toPx() }
    val screenWidthPx = LocalConfiguration.current.screenWidthDp * density.density

    Layout(
        content = {
            imageResources.forEach { resId ->
                Image(
                    painter = painterResource(id = resId),
                    contentDescription = null,
                    contentScale = ContentScale.Fit
                )
            }
        },
        modifier = modifier.fillMaxWidth()
    ) { measurables, constraints ->
        // 第一步:测量所有图片在最大高度下的原始尺寸
        val initialPlaceables = measurables.map { measurable ->
            measurable.measure(
                constraints.copy(
                    maxHeight = maxHeightPx.toInt(),
                    minHeight = 0,
                    minWidth = 0
                )
            )
        }

        // 计算最大高度下的总宽度
        val totalWidthAtMaxHeight = initialPlaceables.sumOf { it.width }

        // 确定缩放比例
        val scaleFactor = if (totalWidthAtMaxHeight <= screenWidthPx) {
            1f
        } else {
            screenWidthPx / totalWidthAtMaxHeight
        }

        val targetHeight = (maxHeightPx * scaleFactor).toInt()

        // 第二步:按缩放后的高度重新测量图片,保持原比例
        val scaledPlaceables = initialPlaceables.mapIndexed { index, placeable ->
            val aspectRatio = placeable.width.toFloat() / placeable.height.toFloat()
            val targetWidth = (targetHeight * aspectRatio).toInt()
            measurables[index].measure(
                constraints.copy(
                    minWidth = targetWidth,
                    maxWidth = targetWidth,
                    minHeight = targetHeight,
                    maxHeight = targetHeight
                )
            )
        }

        // 布局所有图片
        layout(screenWidthPx.toInt(), targetHeight) {
            var xOffset = 0
            scaledPlaceables.forEach { placeable ->
                placeable.placeRelative(x = xOffset, y = 0)
                xOffset += placeable.width
            }
        }
    }
}

使用示例

@Composable
fun DemoScreen() {
    AdaptiveImageRow(
        maxImageHeight = 15.dp,
        imageResources = listOf(
            R.drawable.img_1,
            R.drawable.img_2,
            R.drawable.img_3,
            R.drawable.img_4
            // 添加更多图片资源
        )
    )
}

关键细节说明

  • 用LocalConfiguration获取屏幕宽度,LocalDensity处理dp与像素的转换,确保适配不同设备
  • contentScale = ContentScale.Fit保证图片完整显示,不会被裁剪;若需要图片填充高度,可改为ContentScale.FillHeight
  • 自定义Layout完全控制测量和摆放逻辑,确保所有图片始终保持统一高度,且在宽度不足时等比例缩放

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 01:15:38