Paint API之—— Shader(图像渲染)

Paint API 之—— Shader (图像渲染)

在 Android 的绘图系统中,Paint 类的 Shader 是一个强大的工具,用于定义绘制内容的颜色填充方式。Shader 允许开发者为绘制操作(如路径、形状、文本或位图)指定复杂的颜色渐变、图案填充或其他视觉效果,替代单一的颜色填充。简单来说,Shader 就像给画笔指定了一块“调色板”,让绘制的内容呈现出渐变、纹理或图像效果。

Shader 的作用与应用场景

  • 作用Shader 定义了如何为 Canvas 上的绘制区域填充颜色或纹理。它可以应用到任何使用 Paint 的绘制操作(如 drawRectdrawPathdrawText),并支持矩阵变换(如缩放、旋转)来调整渲染效果。
  • 应用场景
  • 渐变背景(如线性渐变、径向渐变)。
  • 复杂 UI 元素(如按钮的渐变填充)。
  • 图像纹理填充(如用位图填充路径)。
  • 动态效果(如波光粼粼的动画)。
  • 文字特效(如渐变文字或图案文字)。

要使用 Shader,通过 Paint.setShader(Shader shader) 方法设置,传入 null 可清除效果。Shader 不受 PaintStyle(描边或填充)限制,但通常与 FILLFILL_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);
    }
}
  • 运行效果:从上到下依次显示线性渐变矩形、径向渐变圆、扫描渐变圆、位图纹理矩形、组合渐变矩形。
  • 动画扩展:通过 MatrixShader.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 下的高级用法,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注