Compose中Image的使用

一、核心概念与基础用法

1. 核心参数

Image 最基础的构造函数包含 3 个核心参数:

参数名 作用
painter 图片绘制器(核心,指定图片来源)
contentDescription 图片描述(无障碍适配,必填;无描述则传 null,但需加 Modifier.semantics { contentDescription = null }
modifier 布局 / 样式修饰符(尺寸、裁剪、缩放、点击等)

2. 基础示例(加载本地资源图片)

kotlin 复制代码
@Composable
fun BasicImageDemo() {
    // 加载 res/drawable 目录下的图片(如 ic_launcher.png)
    Image(
        painter = painterResource(id = R.drawable.ic_launcher_background),
        contentDescription = "应用图标", // 无障碍描述
        modifier = Modifier
            .size(100.dp) // 设置图片宽高(宽高相同用 size,不同用 width/height)
            .padding(16.dp)
    )
}

二、图片来源(painter 的多种实现)

painterImage 的核心,不同图片来源对应不同的 Painter 实现:

图片来源 实现方式 适用场景
本地资源(res/drawable) painterResource(id = R.drawable.xxx) 应用内置图片(图标、背景)
网络图片 第三方库(Coil/Glide)提供的 rememberAsyncImagePainter 远程图片(接口返回的 URL)
本地文件 / Uri rememberImagePainter(File("/path/to/img"))(Coil) 手机本地文件图片
矢量图(VectorDrawable) painterResource(id = R.drawable.ic_vector) 矢量图标(适配不同分辨率)

关键示例:加载网络图片(主流方案:Coil 库)

Compose 官方推荐用 Coil 加载网络图片,步骤如下:

  1. 添加依赖(build.gradle.kts):
scss 复制代码
dependencies {
    // Coil for Compose
    implementation("io.coil-kt:coil-compose:2.6.0")
}

2.使用示例

ini 复制代码
@Composable
fun NetworkImageDemo() {
    val imageUrl = "https://img1.baidu.com/it/u=600722015,3838115472&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=750"

    // 加载网络图片(rememberAsyncImagePainter 自动处理缓存、加载状态)
    val painter = rememberAsyncImagePainter(
        model = imageUrl,
        // 配置加载占位符/错误占位符
        placeholder = painterResource(id = R.drawable.ic_launcher_background),
        error = painterResource(id = R.drawable.ic_launcher_background)
    )

    Image(
        painter = painter,
        contentDescription = "网络图片",
        modifier = Modifier
            .size(200.dp)
            .clip(RoundedCornerShape(8.dp)), // 圆角裁剪
        contentScale = ContentScale.Crop // 缩放模式
    )
}

三、核心样式配置

1. 缩放模式(contentScale)

控制图片如何适配 Image 的尺寸(类似 ImageViewscaleType),常用值:

作用
ContentScale.Fit 等比例缩放,图片完整显示(可能留空白)
ContentScale.Crop 等比例缩放,填满容器(超出部分裁剪,常用作头像 / 封面)
ContentScale.FillBounds 拉伸图片填满容器(可能变形,不推荐)
ContentScale.Center 图片居中显示,不缩放(超出部分裁剪)
ContentScale.Inside 类似 Fit,但图片尺寸不超过原始尺寸

示例:

ini 复制代码
Image(
painter = painterResource(id = R.drawable.test_img),
contentDescription = "缩放示例",
modifier = Modifier.size(200.dp),
contentScale = ContentScale.Crop // 裁剪填充
)

2. 裁剪与形状(modifier + Clip)

通过 modifier.clip() 实现图片裁剪,支持多种形状:

ini 复制代码
@Composable
fun ImageClipDemo() {
    Column(modifier = Modifier.padding(16.dp)) {
        // 1. 圆角图片
        Image(
            painter = painterResource(id = R.drawable.ic_launcher_background),
            contentDescription = "圆角图片",
            modifier = Modifier
                .size(100.dp)
                .clip(RoundedCornerShape(16.dp)), // 圆角半径
            contentScale = ContentScale.Crop
        )

        Spacer(modifier = Modifier.height(16.dp))

        // 2. 圆形图片(头像常用)
        Image(
            painter = painterResource(id = R.drawable.ic_launcher_background),
            contentDescription = "圆形头像",
            modifier = Modifier
                .size(100.dp)
                .clip(CircleShape), // 圆形裁剪
            contentScale = ContentScale.Crop
        )

        Spacer(modifier = Modifier.height(16.dp))

        // 3. 自定义形状(如矩形带倒角)
        Image(
            painter = painterResource(id = R.drawable.ic_launcher_background),
            contentDescription = "自定义形状",
            modifier = Modifier
                .size(100.dp)
                .clip(RoundedCornerShape(topStart = 20.dp, bottomEnd = 20.dp)),
            contentScale = ContentScale.Crop
        )
    }
}

3. 边框与阴影

结合 bordershadow 修饰符给图片加边框 / 阴影:

ini 复制代码
@Composable
fun ImageBorderShadowDemo() {
    Image(
        painter = painterResource(id = R.drawable.ic_launcher_background),
        contentDescription = "带边框和阴影的图片",
        modifier = Modifier
            .size(100.dp)
            .shadow( // 阴影:半径、颜色、偏移
                elevation = 8.dp,
                shape = CircleShape,
                //color = Color.Gray.copy(alpha = 0.5f)
            )
            .clip(CircleShape) // 先裁剪形状,再加边框
            .border( // 边框:宽度、颜色、形状
                width = 2.dp,
                color = Color.Blue,
                shape = CircleShape
            ),
        contentScale = ContentScale.Crop
    )
}

4. 点击事件

通过 modifier.clickable 给图片加点击 / 长按事件:

ini 复制代码
@Composable
fun ClickableImageDemo() {
    //在最外层获取
    val context = LocalContext.current
    Image(
        painter = painterResource(id = R.drawable.ic_launcher_background),
        contentDescription = "可点击图片",
        modifier = Modifier
            .size(100.dp)
            .clip(CircleShape)
            .clickable( // 点击事件
                onClick = {
                    Toast.makeText(context, "图片被点击", Toast.LENGTH_SHORT).show()
                },
            ),
        contentScale = ContentScale.Crop
    )
}

四、进阶用法

1. 加载状态处理(网络图片)

监听网络图片的加载状态(加载中、成功、失败),自定义界面:

ini 复制代码
@Composable
fun ImageLoadingStateDemo() {
    val imageUrl = "https://img2.baidu.com/it/u=2376489989,3127732063&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=657"
    val painter = rememberAsyncImagePainter(
        model = imageUrl,
        placeholder = painterResource(id = R.drawable.ic_launcher_background)
    )

    // 获取加载状态
    val state = painter.state
    Column(modifier = Modifier.padding(16.dp)) {
        Image(
            painter = painter,
            contentDescription = "加载状态示例",
            modifier = Modifier.size(200.dp),
            contentScale = ContentScale.Crop
        )

        // 根据状态显示提示文字
        when (state) {
            is AsyncImagePainter.State.Loading -> {
                Text(text = "图片加载中...", modifier = Modifier.padding(top = 8.dp))
            }
            is AsyncImagePainter.State.Success -> {
                Text(text = "图片加载成功", modifier = Modifier.padding(top = 8.dp))
            }
            is AsyncImagePainter.State.Error -> {
                Text(
                    text = "图片加载失败",
                    color = Color.Red,
                    modifier = Modifier.padding(top = 8.dp)
                )
            }
            else -> {}
        }
    }
}

2. 图片淡入动画

给图片添加加载完成后的淡入效果:

ini 复制代码
@Composable
fun ImageFadeInDemo() {
    val imageUrl = "https://img2.baidu.com/it/u=2376489989,3127732063&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=657"
    val painter = rememberAsyncImagePainter(model = imageUrl)
    // 动画状态:加载成功后从 0f 变为 1f
    val alpha by animateFloatAsState(
        targetValue = if (painter.state is AsyncImagePainter.State.Success) 1f else 0f,
        animationSpec = tween(durationMillis = 500) // 动画时长 500ms
    )

    Image(
        painter = painter,
        contentDescription = "淡入图片",
        modifier = Modifier
            .size(200.dp)
            .alpha(alpha), // 透明度动画
        contentScale = ContentScale.Crop
    )
}

五、性能优化与注意事项

1. 性能优化

  • 缓存图片资源 :本地图片用 remember 缓存 Painter(避免每次重组重新加载):

    kotlin

    ini 复制代码
    val painter = remember { painterResource(id = R.drawable.test_img) }
  • 网络图片优化 :Coil 已内置缓存(内存 + 磁盘),无需额外处理;避免频繁修改 model(如 URL)导致重复请求。

  • 尺寸优化 :给 Image 明确设置 size/width/height,避免图片自适应导致的额外布局计算。

  • 避免过度绘制 :图片加背景时,优先用 modifier.background() 而非嵌套 Box,减少层级。

2. 常见坑点

坑点 解决方案
contentDescription 报错 必传参数:有描述则传字符串,无描述则传 null + Modifier.semantics { contentDescription = null }
图片拉伸变形 contentScale = ContentScale.Crop/Fit,避免 FillBounds
圆形图片有锯齿 clip(CircleShape) 前加 shadow(微小阴影),或用高分辨率图片
网络图片加载失败无提示 监听 painter.state,显示错误占位符 / 提示文字
图片边框超出裁剪范围 clipborder(顺序不能反),且边框形状和裁剪形状保持一致

六、总结

  1. Image 核心是 painter(图片来源) + modifier(布局 / 样式) + contentScale(缩放),本地图片用 painterResource,网络图片优先用 Coil 的 rememberAsyncImagePainter
  2. 样式配置重点:contentScale 控制缩放(Crop/Fit 最常用),clip 控制裁剪(圆形 / 圆角),border/shadow 增强视觉效果;
  3. 进阶技巧:监听加载状态实现占位 / 错误提示,结合动画实现淡入效果,注意性能优化(缓存、明确尺寸)和坑点(参数顺序、无障碍描述)。
相关推荐
simplepeng3 天前
再见 PredictiveBackHandler:如何迁移到 Compose 中的新导航事件
android jetpack
alexhilton3 天前
在Compose中用Shader实现透明的粘稠元球效果
android·kotlin·android jetpack
ljt27249606616 天前
Compose笔记(七十四)--BlurMaskFilter
笔记·android jetpack
ljt27249606616 天前
Compose笔记(七十五)--withFrameNanos
笔记·android jetpack
hnlgzb7 天前
请详细解释一下MVVM这个设计模型
android·kotlin·android jetpack·compose
hnlgzb9 天前
目前编写安卓app的话有哪几种设计模式?
android·设计模式·kotlin·android jetpack·compose
png10 天前
从零开始Compose天气预报(完结)
android jetpack
阿巴斯甜10 天前
produceState的使用:
android jetpack
阿巴斯甜10 天前
snapshotFlow的使用
android jetpack
菜鸟国国10 天前
从0开始学Jetpack Compose|第二篇:基础组件+核心布局,从零搭建实用UI
android jetpack