Compose中Icon的使用:

11 阅读5分钟

一、核心概念与基础用法

在 Jetpack Compose 中,Icon 组件是专门用于显示矢量图标 / 位图图标的轻量化控件,相比 Image 更适配图标场景(默认正方形、内置图标尺寸规范、支持 Material Design 图标库)。下面从基础用法、图标来源、样式配置、进阶场景四个维度,详细总结 Icon 的核心用法:

1. 核心参数

Icon 的核心参数比 Image 更简洁,适配图标场景:

参数名作用
painter图标绘制器(指定图标来源,支持矢量图 / 位图)
contentDescription图标描述(无障碍适配:纯装饰性图标传 null,功能性图标传描述)
modifier布局 / 样式修饰符(尺寸、颜色、点击等)
tint图标着色(统一修改图标颜色,默认继承父组件颜色,比 Image 更常用)
//也可以使用ImageVector
@Composable
fun Icon(
    imageVector: ImageVector,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current
) {
    Icon(
        painter = rememberVectorPainter(imageVector),
        contentDescription = contentDescription,
        modifier = modifier,
        tint = tint
    )
}
//ImageVector 也可以加载本地图片
imageVector = ImageVector.vectorResource(R.drawable.ic_launcher_background),

2. 基础示例(Material 内置图标)

Compose 内置了 Material Design 图标库(material-icons-core/material-icons-extended),是最常用的图标来源:

@Composable
fun BasicIconDemo() {
    Column {
        // 1. 基础用法:显示 Material 内置图标
        Icon(
            imageVector = ImageVector.vectorResource(R.drawable.ic_launcher_background),
            //  painter = painterResource(id = R.drawable.ic_launcher_background), // 内置图标(24dp 规范)
            contentDescription = "首页图标", // 功能性图标:传描述(无障碍适配)
            modifier = Modifier.size(24.dp), // 图标尺寸(Material 规范:24dp/18dp/20dp)
            tint = Color.Blue // 图标着色(统一修改颜色,无需改图标文件)
        )

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

        // 2. 装饰性图标:contentDescription 传 null(需配合 semantics)
        Icon(
            painter = painterResource(id = R.drawable.ic_launcher_background),
            contentDescription = null, // 纯装饰,无功能
            modifier = Modifier
                .size(20.dp)
                .semantics { contentDescription = "" }, // 解决无障碍报错
            tint = Color.Yellow
        )
    }

}

二、图标来源(painter 的 3 种核心方式)

Icon 的 painter 支持 3 类图标来源,覆盖绝大部分场景:

图标来源实现方式适用场景
Material 内置图标painterResource(id = R.drawable.ic_baseline_xxx_24)通用图标(首页、返回、搜索等)
自定义矢量图标(SVG)painterResource(id = R.drawable.ic_custom_vector)应用专属图标(需导入 SVG 到 res/drawable)
位图图标(PNG/JPG)painterResource(id = R.drawable.ic_custom_png)非矢量图标(不推荐,缩放易模糊)

关键补充:导入 Material 内置图标

  1. 添加依赖(build.gradle.kts):
dependencies {
    // 基础 Material 图标(常用 24dp 图标)
    implementation("androidx.compose.material:material-icons-core:1.6.0")
    // 扩展图标库(更多图标,按需添加)
    implementation("androidx.compose.material:material-icons-extended:1.6.0")
}

2.直接使用内置图标常量(更简洁):

@Composable
fun MaterialIconConstantDemo() {
    Column {
        // 直接使用 Material 图标常量(无需手动导入资源)
        Icon(
            imageVector = Icons.Default.Home, // 内置 Home 图标(Vector 类型)
            contentDescription = "首页",
            modifier = Modifier.size(24.dp),
            tint = Color.Black
        )

        // 扩展图标(需添加 material-icons-extended 依赖)
        Icon(
            imageVector = Icons.Default.Shop,
            contentDescription = "购物车",
            modifier = Modifier.size(24.dp)
        )

    }

}

⚠️ 区别:imageVector 直接接收 ImageVector 类型(内置图标常量),painter 接收 Painter 类型(本地资源),两者是 Icon 的两个重载构造函数,功能等价。

三、核心样式配置

1. 尺寸控制(Material 规范)

Material Design 推荐图标尺寸:

  • 24dp(默认,按钮 / 导航栏图标);
  • 20dp(次级操作图标);
  • 18dp(文本旁辅助图标)。

示例:

Icon(
imageVector = Icons.Default.Search,
contentDescription = "搜索",
modifier = Modifier
.size(24.dp) // 正方形(宽高相同)
// .width(20.dp).height(20.dp) // 自定义尺寸(非正方形)
)

2. 着色(tint)—— 最常用样式

int 可以统一修改图标颜色(无需修改图标文件),支持纯色 / 渐变:

@Composable
fun IconTintDemo() {
    Column(modifier = Modifier.padding(16.dp)) {
        // 1. 纯色着色
        Icon(
            imageVector = Icons.Default.Favorite,
            contentDescription = "收藏",
            modifier = Modifier.size(24.dp),
            tint = Color.Red
        )

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

        // 2. 渐变着色(需通过 modifier 实现)
        Icon(
            imageVector = Icons.Default.Star,
            contentDescription = "评分",
            modifier = Modifier
                .size(24.dp)
                .background(
                    brush = Brush.linearGradient(
                        colors = listOf(Color.Yellow, Color.Blue)
                    ),
                    shape = CircleShape
                ),
               // .mask(Icon(Icons.Default.Star, contentDescription = null)), // 蒙版实现渐变
            tint = Color.Transparent // 透明底色,显示渐变背景
        )
    }
}

3. 裁剪与形状

通过 modifier.clip() 实现图标裁剪(如圆形、圆角)

@Composable
fun IconClipDemo() {
    Icon(
        imageVector = Icons.Default.Person,
        contentDescription = "头像图标",
        modifier = Modifier
            .size(40.dp)
            .clip(CircleShape) // 圆形裁剪
            .background(Color.LightGray), // 加背景色
        tint = Color.White
    )
}

4. 边框与阴影

结合 border/shadow 增强视觉效果:

@Composable
fun IconBorderShadowDemo() {
    Icon(
        imageVector = Icons.Default.Setting,
        contentDescription = "设置",
        modifier = Modifier
            .size(24.dp)
            .shadow(
                elevation = 4.dp,
                shape = CircleShape,
                color = Color.Gray.copy(alpha = 0.5f)
            )
            .border(
                width = 1.dp,
                color = Color.Blue,
                shape = CircleShape
            ),
        tint = Color.Black
    )
}

五、性能优化与注意事项

1. 性能优化

  • 缓存图标资源:静态图标用 remember 缓存 Painter/ImageVector,避免每次重组重新加载:

    kotlin

    val homeIcon = remember { Icons.Default.Home }
    Icon(imageVector = homeIcon, contentDescription = "首页")
    
  • 优先使用矢量图标:SVG 矢量图标缩放无模糊,且体积小,优于 PNG 位图;

  • 避免过度着色tint 是轻量操作,但渐变着色(蒙版方式)会增加布局层级,高频使用需谨慎;

  • 统一图标尺寸:避免频繁修改图标尺寸,减少布局计算开销。

2. 常见坑点

坑点解决方案
contentDescription 报错功能性图标传描述(如 "首页"),装饰性图标传 null + Modifier.semantics { contentDescription = null }
图标着色无效1. 检查图标文件是否为单色(多色图标 tint 会覆盖所有颜色);2. 确认 tint 未设为 Color.Unspecified
矢量图标缩放模糊确保导入的 SVG 图标是矢量格式(不是位图转 SVG),且尺寸符合 Material 规范
图标点击区域过小给 modifier 加 padding(如 padding(4.dp)),扩大点击区域
ImageVector 找不到扩展图标需添加 material-icons-extended 依赖,且导入正确的包(androidx.compose.material.icons.extended.Icons

六、Icon 与 Image 的区别(选型参考)

特性Icon 组件Image 组件
核心用途小尺寸图标(矢量优先)图片显示(位图 / 网络图片)
默认尺寸24dp(正方形)无默认尺寸,需手动设置
着色支持内置 tint 参数(更友好)需通过 colorFilter 实现
无障碍适配装饰性图标可直接传 null(配 semantics)必须传 contentDescription 或配 semantics
推荐场景按钮、导航栏、文本旁的小图标封面、头像、网络图片等