Paint API之—— Shader(图像渲染)
Paint API 之—— Shader (图像渲染)
在 Android 的绘图系统中,Paint
类的 Shader
是一个强大的工具,用于定义绘制内容的颜色填充方式。Shader
允许开发者为绘制操作(如路径、形状、文本或位图)指定复杂的颜色渐变、图案填充或其他视觉效果,替代单一的颜色填充。简单来说,Shader
就像给画笔指定了一块“调色板”,让绘制的内容呈现出渐变、纹理或图像效果。
Shader 的作用与应用场景
- 作用:
Shader
定义了如何为Canvas
上的绘制区域填充颜色或纹理。它可以应用到任何使用Paint
的绘制操作(如drawRect
、drawPath
、drawText
),并支持矩阵变换(如缩放、旋转)来调整渲染效果。 - 应用场景:
- 渐变背景(如线性渐变、径向渐变)。
- 复杂 UI 元素(如按钮的渐变填充)。
- 图像纹理填充(如用位图填充路径)。
- 动态效果(如波光粼粼的动画)。
- 文字特效(如渐变文字或图案文字)。
要使用 Shader
,通过 Paint.setShader(Shader shader)
方法设置,传入 null
可清除效果。Shader
不受 Paint
的 Style
(描边或填充)限制,但通常与 FILL
或 FILL_AND_STROKE
搭配使用以展现完整效果。
Shader 的主要子类
Shader
是一个抽象类,实际使用其子类。以下是常见的 Shader
子类及其用法:
子类 | 描述 | 构造函数示例 | 效果示例 |
---|---|---|---|
LinearGradient | 线性渐变,从起点到终点按指定颜色渐变。支持多色点和分布方式。 | new LinearGradient(0, 0, 100, 100, Color.RED, Color.BLUE, Shader.TileMode.CLAMP) | 直线渐变 |
RadialGradient | 径向渐变,从中心点向外扩散的圆形渐变。 | new RadialGradient(100, 100, 50, Color.RED, Color.BLUE, Shader.TileMode.CLAMP) | 圆形渐变 |
SweepGradient | 扫描渐变(角度渐变),围绕中心点按角度旋转渐变。 | new SweepGradient(100, 100, Color.RED, Color.BLUE) | 扇形渐变 |
BitmapShader | 用位图作为纹理填充,支持平铺模式(CLAMP、REPEAT、MIRROR)。 | new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT) | 图像纹理 |
ComposeShader | 组合两个 Shader,通过特定模式(如 PorterDuff 模式)混合效果。 | new ComposeShader(shaderA, shaderB, PorterDuff.Mode.SRC_OVER) | 渐变叠加 |
TileMode 说明(用于 LinearGradient、RadialGradient、BitmapShader):
CLAMP
:边缘拉伸(用边缘颜色填充)。REPEAT
:重复平铺。MIRROR
:镜像平铺。
代码示例
以下是一个自定义 View 示例,展示不同 Shader 的效果。复制到 Android 项目中运行,可在画布上看到渐变和纹理效果。
import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.view.View;
public class ShaderView extends View {
private Paint paint;
public ShaderView(Context context, AttributeSet attrs) {
super(context, attrs);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 1. 线性渐变
Shader linearGradient = new LinearGradient(50, 50, 200, 50, Color.RED, Color.BLUE, Shader.TileMode.CLAMP);
paint.setShader(linearGradient);
canvas.drawRect(50, 50, 200, 150, paint);
// 2. 径向渐变
Shader radialGradient = new RadialGradient(125, 300, 50, Color.GREEN, Color.YELLOW, Shader.TileMode.CLAMP);
paint.setShader(radialGradient);
canvas.translate(0, 200);
canvas.drawCircle(125, 50, 50, paint);
// 3. 扫描渐变
Shader sweepGradient = new SweepGradient(125, 300, Color.BLUE, Color.RED);
paint.setShader(sweepGradient);
canvas.translate(0, 200);
canvas.drawCircle(125, 50, 50, paint);
// 4. 位图纹理(需准备一个 bitmap)
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample_image); // 替换为你的图片资源
Shader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
paint.setShader(bitmapShader);
canvas.translate(0, 200);
canvas.drawRect(50, 50, 200, 150, paint);
// 5. 组合 Shader
Shader linear = new LinearGradient(50, 450, 200, 450, Color.RED, Color.BLUE, Shader.TileMode.CLAMP);
Shader radial = new RadialGradient(125, 500, 50, Color.GREEN, Color.YELLOW, Shader.TileMode.CLAMP);
Shader composeShader = new ComposeShader(linear, radial, PorterDuff.Mode.MULTIPLY);
paint.setShader(composeShader);
canvas.translate(0, 200);
canvas.drawRect(50, 50, 200, 150, paint);
}
}
- 运行效果:从上到下依次显示线性渐变矩形、径向渐变圆、扫描渐变圆、位图纹理矩形、组合渐变矩形。
- 动画扩展:通过
Matrix
和Shader.setLocalMatrix()
可以动态变换 Shader(如平移或旋转渐变),实现动画效果。例如,动态改变 LinearGradient 的起点和终点可模拟光晕移动。
注意事项
- 性能:复杂 Shader(如多色渐变或大位图的 BitmapShader)可能影响性能,建议优化绘制区域或缓存到 Bitmap。
- 兼容性:Shader 自 API 1 起支持,无需额外权限。
- 矩阵变换:Shader 默认基于画布坐标系,通过
setLocalMatrix()
可调整其位置、缩放或旋转。 - 与 PathEffect 的结合:Shader 负责颜色填充,PathEffect 负责路径形状,两者可组合使用(如渐变虚线)。
- 调试:Android SDK 的 ApiDemos 有 Shader 示例,可参考学习。
扩展:Jetpack Compose 中的等效实现
在 Jetpack Compose 中,Shader
的功能主要通过 Brush
类实现,例如:
Brush.linearGradient
:对应 LinearGradient。Brush.radialGradient
:对应 RadialGradient。Brush.sweepGradient
:对应 SweepGradient。- 位图纹理可通过
ImageShader
实现。
示例(Compose 中的线性渐变):
import androidx.compose.foundation.Canvas
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.LinearGradient
@Composable
fun GradientExample() {
Canvas(modifier = Modifier.size(200.dp)) {
drawRect(
brush = LinearGradient(
colors = listOf(Color.Red, Color.Blue),
start = Offset(0f, 0f),
end = Offset(200f, 0f)
),
style = Fill
)
}
}
总结
Shader
是 Android 绘图中实现丰富视觉效果的核心工具,适合创建渐变、纹理和复杂填充样式。结合矩阵变换或动画,可以实现动态效果。如果需要更详细的某类 Shader 示例(如多色渐变或动态纹理动画)、性能优化建议,或 Compose 下的高级用法,请告诉我!