Jetpack Compose Brush 渐变
目录
一、Brush类基础概念
1.1 什么是Brush
在Jetpack Compose中,Brush是一个抽象类,用于定义**着色器(Shader)**的创建方式。它是Compose图形系统的核心组件之一,负责描述如何将颜色应用到绘制区域。
kotlin
// Brush位于androidx.compose.ui.graphics包中
abstract class Brush {
abstract fun applyTo(size: Size, paint: Paint, alpha: Float = 1.0f)
// 创建着色器的内部方法
internal abstract fun createShader(size: Size): Shader
}
1.2 Brush在Compose中的定位
css
Compose图形渲染层级:
┌─────────────────────────────────────┐
│ UI组件层 │
│ (Box, Text, Button, Canvas...) │
├─────────────────────────────────────┤
│ Modifier层 │
│ (background, border, drawWith...) │
├─────────────────────────────────────┤
│ Brush层 │
│ (LinearGradient, RadialGradient) │
├─────────────────────────────────────┤
│ Paint/Shader层 │
│ (Android底层图形API) │
└─────────────────────────────────────┘
1.3 Brush的核心特性
| 特性 | 说明 |
|---|---|
| 延迟计算 | Brush在绘制时才根据实际尺寸创建Shader |
| 尺寸自适应 | 自动适应目标组件的尺寸变化 |
| 可复用性 | 同一个Brush实例可应用于多个组件 |
| 动画支持 | 支持配合animate*函数实现动态渐变效果 |
二、渐变类型详解
2.1 LinearGradient(线性渐变)
线性渐变是最常用的渐变类型,颜色沿一条直线从起点过渡到终点。
2.1.1 基础构造函数
kotlin
// 方式1:使用Offset指定起点和终点
fun LinearGradient(
colors: List<Color>, // 颜色列表(至少2个)
start: Offset, // 渐变起点坐标
end: Offset, // 渐变终点坐标
tileMode: TileMode = TileMode.Clamp // 平铺模式
): Brush
// 方式2:使用颜色与位置配对
fun LinearGradient(
colorStops: List<Pair<Float, Color>>, // 颜色停止点(位置0.0-1.0, 颜色)
start: Offset,
end: Offset,
tileMode: TileMode = TileMode.Clamp
): Brush
2.1.2 参数详解
坐标系统说明:
arduino
(0,0) ─────────────────── (width,0)
│ │
│ 组件区域 │
│ │
(0,height) ───────── (width,height)
常用渐变方向:
kotlin
// 水平渐变(左到右)
val horizontalGradient = Brush.linearGradient(
colors = listOf(Color.Red, Color.Blue),
start = Offset(0f, 0f),
end = Offset(Float.POSITIVE_INFINITY, 0f) // 或使用具体宽度
)
// 垂直渐变(上到下)
val verticalGradient = Brush.linearGradient(
colors = listOf(Color.Red, Color.Blue),
start = Offset(0f, 0f),
end = Offset(0f, Float.POSITIVE_INFINITY)
)
// 对角线渐变
val diagonalGradient = Brush.linearGradient(
colors = listOf(Color.Red, Color.Blue),
start = Offset(0f, 0f),
end = Offset(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
)
TileMode(平铺模式):
| 模式 | 说明 | 视觉效果 |
|---|---|---|
Clamp |
边缘颜色延伸(默认) | 边缘颜色无限延伸 |
Repeated |
重复渐变图案 | 周期性重复 |
Mirror |
镜像重复 | 正反交替重复 |
Decal |
透明延伸 | 边缘外透明 |
2.1.3 颜色分布控制
kotlin
// 使用colorStops精确控制颜色分布
val preciseGradient = Brush.linearGradient(
colorStops = listOf(
0.0f to Color.Red, // 起点:红色
0.3f to Color.Yellow, // 30%位置:黄色
0.7f to Color.Green, // 70%位置:绿色
1.0f to Color.Blue // 终点:蓝色
),
start = Offset.Zero,
end = Offset.Infinite
)
2.2 RadialGradient(径向渐变)
径向渐变从中心点向外辐射,颜色从中心向边缘过渡。
2.2.1 构造函数
kotlin
fun RadialGradient(
colors: List<Color>,
center: Offset, // 渐变中心点
radius: Float, // 渐变半径
tileMode: TileMode = TileMode.Clamp
): Brush
// 带颜色停止点的版本
fun RadialGradient(
colorStops: List<Pair<Float, Color>>,
center: Offset,
radius: Float,
tileMode: TileMode = TileMode.Clamp
): Brush
2.2.2 参数详解与应用
kotlin
// 基础径向渐变
val basicRadial = Brush.radialGradient(
colors = listOf(Color.White, Color.Black),
center = Offset(150f, 150f), // 中心点坐标
radius = 200f // 半径(像素)
)
// 中心对齐的径向渐变(使用组件尺寸)
val centeredRadial = Brush.radialGradient(
colors = listOf(
Color(0xFF667eea),
Color(0xFF764ba2)
),
center = Offset(0.5f, 0.5f), // 使用比例定位中心
radius = 0.5f // 使用比例作为半径
)
注意事项:
- 半径值超过目标区域时,
TileMode决定外部如何填充 - 中心点可以使用绝对坐标或相对比例
- 适合创建发光、 spotlight、圆形按钮等效果
2.3 SweepGradient(扫描渐变/角度渐变)
扫描渐变围绕中心点按角度旋转分布颜色,类似雷达扫描效果。
2.3.1 构造函数
kotlin
fun SweepGradient(
colors: List<Color>,
center: Offset // 旋转中心点
): Brush
// 带颜色停止点
fun SweepGradient(
colorStops: List<Pair<Float, Color>>,
center: Offset
): Brush
2.3.2 角度计算原理
scss
270° (-90°)
│
│
180° ────┼──── 0° (360°)
│
│
90°
颜色分布从0°开始,顺时针方向排列
kotlin
// 彩虹色扫描渐变
val rainbowSweep = Brush.sweepGradient(
colorStops = listOf(
0.0f to Color.Red, // 0°
0.17f to Color.Yellow, // ~60°
0.33f to Color.Green, // ~120°
0.5f to Color.Cyan, // 180°
0.67f to Color.Blue, // ~240°
0.83f to Color.Magenta, // ~300°
1.0f to Color.Red // 360°
),
center = Offset(0.5f, 0.5f)
)
2.3.3 应用场景
- 圆形进度指示器
- 色轮/颜色选择器
- 雷达扫描动画效果
- 仪表盘刻度背景
2.4 ShaderBrush(自定义着色器Brush)
对于更复杂的渐变需求,可以使用ShaderBrush创建自定义着色器。
kotlin
// 使用RuntimeShader创建复杂效果(API 33+)
val customShaderBrush = object : ShaderBrush() {
override fun createShader(size: Size): Shader {
return RuntimeShader("""
vec4 main(vec2 coord) {
float t = coord.x / ${size.width};
return vec4(t, 0.0, 1.0 - t, 1.0);
}
""").apply {
setFloatUniform("resolution", size.width, size.height)
}
}
}
// 使用Compose内置的AgSL着色器
val noiseBrush = ShaderBrush(
RuntimeShader(NoiseShader).apply {
setFloatUniform("resolution", 100f, 100f)
}
)
三、UI组件应用方法
3.1 作为background属性
kotlin
// 基础用法
Box(
modifier = Modifier
.size(200.dp)
.background(
brush = Brush.linearGradient(
colors = listOf(Color.Red, Color.Blue)
)
)
)
// 带形状的背景
Box(
modifier = Modifier
.size(200.dp)
.background(
brush = Brush.radialGradient(
colors = listOf(Color.Yellow, Color.Transparent)
),
shape = RoundedCornerShape(16.dp)
)
)
3.2 作为border属性
kotlin
Box(
modifier = Modifier
.size(200.dp)
.border(
width = 4.dp,
brush = Brush.linearGradient(
colors = listOf(Color.Cyan, Color.Magenta)
),
shape = CircleShape
)
)
3.3 文本渐变效果
kotlin
// 方式1:使用brush参数(Compose 1.2.0+)
Text(
text = "Gradient Text",
style = TextStyle(
brush = Brush.linearGradient(
colors = listOf(Color.Red, Color.Blue)
),
fontSize = 40.sp,
fontWeight = FontWeight.Bold
)
)
// 方式2:使用drawWithCache实现更复杂效果
Text(
text = "Gradient Text",
modifier = Modifier.drawWithCache {
val brush = Brush.linearGradient(
colors = listOf(Color.Red, Color.Blue),
start = Offset(0f, 0f),
end = Offset(size.width, size.height)
)
onDrawWithContent {
drawContent()
drawRect(
brush = brush,
blendMode = BlendMode.SrcAtop // 只应用于文字
)
}
},
fontSize = 40.sp,
fontWeight = FontWeight.Bold
)
3.4 与Modifier结合的高级技巧
3.4.1 drawBehind - 在内容后绘制
kotlin
Box(
modifier = Modifier
.fillMaxSize()
.drawBehind {
// 绘制网格背景
val gridBrush = Brush.linearGradient(
colors = listOf(Color.Gray.copy(alpha = 0.1f), Color.Transparent),
start = Offset(0f, 0f),
end = Offset(50f, 50f),
tileMode = TileMode.Repeated
)
drawRect(brush = gridBrush)
}
)
3.4.2 drawWithContent - 控制绘制层级
kotlin
Box(
modifier = Modifier
.size(200.dp)
.drawWithContent {
// 1. 先绘制渐变背景
drawRect(
brush = Brush.radialGradient(
colors = listOf(Color.Yellow, Color.Orange)
)
)
// 2. 绘制内容
drawContent()
// 3. 绘制渐变遮罩
drawRect(
brush = Brush.verticalGradient(
colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.3f))
),
blendMode = BlendMode.Multiply
)
}
)
3.5 在Canvas中的高级应用
kotlin
Canvas(modifier = Modifier.fillMaxSize()) {
val canvasWidth = size.width
val canvasHeight = size.height
// 1. 绘制渐变矩形
drawRect(
brush = Brush.linearGradient(
colors = listOf(Color.Red, Color.Blue),
start = Offset(0f, 0f),
end = Offset(canvasWidth, canvasHeight)
),
size = Size(canvasWidth, canvasHeight)
)
// 2. 绘制渐变圆形
drawCircle(
brush = Brush.radialGradient(
colors = listOf(Color.White, Color.Transparent),
center = Offset(canvasWidth / 2, canvasHeight / 2),
radius = 200f
),
radius = 200f,
center = Offset(canvasWidth / 2, canvasHeight / 2)
)
// 3. 绘制渐变路径
val path = Path().apply {
moveTo(0f, canvasHeight)
quadraticBezierTo(
canvasWidth / 2, canvasHeight - 200f,
canvasWidth, canvasHeight
)
lineTo(canvasWidth, canvasHeight + 200f)
lineTo(0f, canvasHeight + 200f)
close()
}
drawPath(
path = path,
brush = Brush.verticalGradient(
colors = listOf(Color.Cyan, Color.Blue)
)
)
}
四、代码示例
示例1:渐变卡片组件(基础应用)
kotlin
@Composable
fun GradientCardDemo() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
// 线性渐变卡片
GradientCard(
title = "Linear Gradient",
description = "Beautiful linear gradient background",
brush = Brush.linearGradient(
colors = listOf(
Color(0xFF667eea),
Color(0xFF764ba2)
),
start = Offset(0f, 0f),
end = Offset(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
)
)
// 径向渐变卡片
GradientCard(
title = "Radial Gradient",
description = "Elegant radial gradient effect",
brush = Brush.radialGradient(
colors = listOf(
Color(0xFFf093fb),
Color(0xFFf5576c)
),
center = Offset(0.3f, 0.3f),
radius = 0.8f
)
)
// 扫描渐变卡片
GradientCard(
title = "Sweep Gradient",
description = "Dynamic sweep gradient pattern",
brush = Brush.sweepGradient(
colorStops = listOf(
0.0f to Color(0xFF4facfe),
0.5f to Color(0xFF00f2fe),
1.0f to Color(0xFF4facfe)
),
center = Offset(0.5f, 0.5f)
)
)
}
}
@Composable
private fun GradientCard(
title: String,
description: String,
brush: Brush
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(120.dp)
.background(
brush = brush,
shape = RoundedCornerShape(16.dp)
)
.padding(20.dp)
) {
Column {
Text(
text = title,
color = Color.White,
fontSize = 24.sp,
fontWeight = FontWeight.Bold
)
Text(
text = description,
color = Color.White.copy(alpha = 0.8f),
fontSize = 14.sp
)
}
}
}
示例2:渐变文字与边框(高级应用)
kotlin
@Composable
fun GradientTextAndBorderDemo() {
Column(
modifier = Modifier
.fillMaxSize()
.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(32.dp)
) {
// 渐变边框按钮
GradientBorderButton(
text = "Gradient Border",
onClick = { }
)
// 渐变文字
GradientText(
text = "GRADIENT",
fontSize = 48.sp
)
// 带渐变遮罩的图片
GradientImageCard()
}
}
@Composable
private fun GradientBorderButton(
text: String,
onClick: () -> Unit
) {
val gradientBrush = Brush.linearGradient(
colors = listOf(
Color(0xFF00c6ff),
Color(0xFF0072ff)
)
)
Box(
modifier = Modifier
.clickable(onClick = onClick)
.border(
width = 3.dp,
brush = gradientBrush,
shape = RoundedCornerShape(50.dp)
)
.padding(horizontal = 32.dp, vertical = 16.dp)
) {
Text(
text = text,
color = Color(0xFF0072ff),
fontSize = 18.sp,
fontWeight = FontWeight.Medium
)
}
}
@Composable
private fun GradientText(
text: String,
fontSize: TextUnit
) {
val gradientBrush = Brush.horizontalGradient(
colors = listOf(
Color(0xFFf093fb),
Color(0xFFf5576c),
Color(0xFF4facfe),
Color(0xFF00f2fe)
)
)
Text(
text = text,
style = TextStyle(
brush = gradientBrush,
fontSize = fontSize,
fontWeight = FontWeight.ExtraBold,
letterSpacing = 4.sp
)
)
}
@Composable
private fun GradientImageCard() {
Box(
modifier = Modifier
.fillMaxWidth()
.height(200.dp)
.clip(RoundedCornerShape(16.dp))
) {
// 模拟图片
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.DarkGray)
)
// 底部渐变遮罩
Box(
modifier = Modifier
.fillMaxSize()
.background(
brush = Brush.verticalGradient(
colors = listOf(
Color.Transparent,
Color.Transparent,
Color.Black.copy(alpha = 0.7f)
)
)
)
)
// 文字内容
Text(
text = "Beautiful Gradient Overlay",
color = Color.White,
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier
.align(Alignment.BottomStart)
.padding(16.dp)
)
}
}
示例3:动态渐变动画(高级场景)
kotlin
@Composable
fun AnimatedGradientDemo() {
// 动画状态
val infiniteTransition = rememberInfiniteTransition(label = "gradient")
// 动画偏移量
val offset by infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(3000, easing = LinearEasing),
repeatMode = RepeatMode.Reverse
),
label = "offset"
)
// 动画颜色
val animatedColor by infiniteTransition.animateColor(
initialValue = Color(0xFF667eea),
targetValue = Color(0xFF764ba2),
animationSpec = infiniteRepeatable(
animation = tween(2000),
repeatMode = RepeatMode.Reverse
),
label = "color"
)
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(24.dp)
) {
// 1. 流动渐变背景
AnimatedGradientBackground(offset)
// 2. 颜色变化渐变
ColorShiftingGradient(animatedColor)
// 3. 扫描渐变动画
RotatingSweepGradient()
// 4. 呼吸效果渐变
PulsingGradient()
}
}
@Composable
private fun AnimatedGradientBackground(offset: Float) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(150.dp)
.padding(16.dp)
.background(
brush = Brush.linearGradient(
colors = listOf(
Color(0xFFff9a9e),
Color(0xFFfecfef),
Color(0xFFfecfef),
Color(0xFFff9a9e)
),
start = Offset(offset * 1000f, 0f),
end = Offset(offset * 1000f + 500f, 0f)
),
shape = RoundedCornerShape(16.dp)
)
) {
Text(
text = "Flowing Gradient",
color = Color.White,
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.align(Alignment.Center)
)
}
}
@Composable
private fun ColorShiftingGradient(baseColor: Color) {
Box(
modifier = Modifier
.size(150.dp)
.background(
brush = Brush.radialGradient(
colors = listOf(
baseColor,
baseColor.copy(red = baseColor.red * 0.7f),
Color.DarkGray
)
),
shape = CircleShape
),
contentAlignment = Alignment.Center
) {
Text(
text = "Color Shift",
color = Color.White,
fontWeight = FontWeight.Bold
)
}
}
@Composable
private fun RotatingSweepGradient() {
val rotation by rememberInfiniteTransition(label = "rotation")
.animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(4000, easing = LinearEasing)
),
label = "rotation"
)
Box(
modifier = Modifier
.size(150.dp)
.drawWithCache {
val brush = Brush.sweepGradient(
colorStops = listOf(
0.0f to Color.Transparent,
0.3f to Color(0xFF00c6ff),
0.7f to Color(0xFF0072ff),
1.0f to Color.Transparent
),
center = Offset(size.width / 2, size.height / 2)
)
onDrawWithContent {
rotate(rotation) {
drawCircle(
brush = brush,
radius = size.minDimension / 2
)
}
}
}
)
}
@Composable
private fun PulsingGradient() {
val scale by rememberInfiniteTransition(label = "pulse")
.animateFloat(
initialValue = 0.8f,
targetValue = 1.2f,
animationSpec = infiniteRepeatable(
animation = tween(1500),
repeatMode = RepeatMode.Reverse
),
label = "scale"
)
Box(
modifier = Modifier
.size(150.dp)
.graphicsLayer {
scaleX = scale
scaleY = scale
}
.background(
brush = Brush.radialGradient(
colors = listOf(
Color(0xFFf093fb).copy(alpha = 0.8f),
Color(0xFFf5576c).copy(alpha = 0.4f),
Color.Transparent
)
),
shape = CircleShape
)
)
}
五、性能优化与最佳实践
5.1 性能优化建议
5.1.1 Brush实例复用
kotlin
// ❌ 错误:每次重组都创建新Brush
@Composable
fun BadExample() {
Box(
modifier = Modifier.background(
brush = Brush.linearGradient(listOf(Color.Red, Color.Blue)) // 每次重组都新建
)
)
}
// ✅ 正确:使用remember缓存Brush
@Composable
fun GoodExample() {
val gradientBrush = remember {
Brush.linearGradient(listOf(Color.Red, Color.Blue))
}
Box(
modifier = Modifier.background(brush = gradientBrush)
)
}
// ✅ 更好:使用静态常量
object GradientBrushes {
val DefaultGradient = Brush.linearGradient(
listOf(Color(0xFF667eea), Color(0xFF764ba2))
)
}
5.1.2 避免过度绘制
kotlin
// ❌ 错误:多层渐变叠加
Box(
modifier = Modifier
.background(Brush.linearGradient(...)) // 第一层
.background(Brush.radialGradient(...)) // 第二层 - 过度绘制
)
// ✅ 正确:合并为单层
Box(
modifier = Modifier
.drawWithCache {
val combinedBrush = // 预计算合并后的效果
onDrawBehind {
drawRect(brush = combinedBrush)
}
}
)
5.1.3 使用drawWithCache优化复杂绘制
kotlin
@Composable
fun OptimizedGradientBox() {
Box(
modifier = Modifier
.fillMaxSize()
.drawWithCache {
// 在缓存中创建Brush,避免每次重绘都重新计算
val gradientBrush = Brush.linearGradient(
colors = listOf(Color.Red, Color.Blue),
start = Offset(0f, 0f),
end = Offset(size.width, size.height)
)
onDrawBehind {
drawRect(brush = gradientBrush)
}
}
)
}
5.2 常见问题解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 渐变颜色断层 | 色深不足/颜色差异大 | 使用更多过渡色,增加颜色停止点 |
| 渐变闪烁 | Brush频繁重建 | 使用remember缓存Brush实例 |
| 尺寸计算错误 | Offset使用绝对值 | 使用drawWithCache获取实际尺寸 |
| 动画卡顿 | 每帧创建Shader | 使用ShaderBrush配合硬件加速 |
| 边缘锯齿 | TileMode设置不当 | 使用Clamp模式或增大渐变区域 |
5.3 最佳实践清单
- 将Brush定义为常量或remember缓存
- 使用
drawWithCache处理复杂渐变效果 - 避免在动画中频繁创建Brush
- 合理选择TileMode避免边缘问题
- 使用colorStops精确控制颜色分布
- 考虑深色模式下的渐变适配
六、与传统View系统对比
6.1 实现方式对比
| 特性 | 传统View (XML/Canvas) | Jetpack Compose |
|---|---|---|
| 线性渐变 | <gradient android:type="linear"/> |
Brush.linearGradient() |
| 径向渐变 | <gradient android:type="radial"/> |
Brush.radialGradient() |
| 扫描渐变 | <gradient android:type="sweep"/> |
Brush.sweepGradient() |
| 代码创建 | LinearGradient Shader |
Brush 类 |
| 动态更新 | 需重新创建Drawable/Shader | 状态驱动自动重组 |
| 动画支持 | 需手动处理ValueAnimator | 直接配合animate*函数 |
6.2 代码对比示例
传统View方式:
kotlin
// XML定义
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:type="linear"
android:angle="45"
android:startColor="#FF667eea"
android:endColor="#FF764ba2" />
</shape>
// 代码动态创建
val paint = Paint().apply {
shader = LinearGradient(
0f, 0f, width, height,
Color.parseColor("#FF667eea"),
Color.parseColor("#FF764ba2"),
Shader.TileMode.CLAMP
)
}
canvas.drawRect(rect, paint)
Compose方式:
kotlin
Box(
modifier = Modifier
.fillMaxSize()
.background(
brush = Brush.linearGradient(
colors = listOf(Color(0xFF667eea), Color(0xFF764ba2)),
start = Offset(0f, 0f),
end = Offset(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
)
)
)
6.3 优劣势分析
Compose Brush优势:
- 声明式语法 - 代码更简洁直观
- 状态驱动 - 自动响应状态变化重绘
- 动画友好 - 无缝集成Compose动画系统
- 类型安全 - 编译时检查,减少运行时错误
- 可组合性 - 易于封装和复用
传统View优势:
- XML预览 - 可在布局编辑器中直观预览
- 成熟生态 - 大量现成工具和库支持
- 性能调优 - 更底层的控制,特定场景更优
6.4 迁移建议
kotlin
// 将XML Gradient Drawable迁移到Compose
// 原XML:
// <shape>
// <gradient android:angle="135" android:startColor="#FF512F" android:endColor="#DD2476"/>
// </shape>
// Compose等效:
val migratedBrush = Brush.linearGradient(
colors = listOf(Color(0xFF512F), Color(0xFFDD2476)),
start = Offset(0f, Float.POSITIVE_INFINITY), // 135度 ≈ 从左下到右上
end = Offset(Float.POSITIVE_INFINITY, 0f)
)
总结
Jetpack Compose的Brush系统为渐变效果提供了强大而灵活的解决方案。通过理解其底层原理和最佳实践,开发者可以:
- 高效创建各类渐变效果(线性、径向、扫描)
- 灵活应用于各种UI组件和自定义绘制场景
- 流畅实现复杂的渐变动画效果
- 优化性能避免常见陷阱
掌握Brush的使用是成为高级Compose开发者的必备技能,希望本指南能帮助您在实际项目中更好地运用渐变效果,打造出色的用户界面。