一、核心概念与基础用法
在 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 内置图标
- 添加依赖(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 |
| 推荐场景 | 按钮、导航栏、文本旁的小图标 | 封面、头像、网络图片等 |