Canvas 的裁剪(Clip)用于限定绘制区域:只有裁剪区域范围内的内容才会被显示出来。

Region.Op 裁剪模式

Canvas 支持多种裁剪区域的组合操作,通过 Region.Op 枚举指定:

枚举值说明
DIFFERENCE(0)最终区域为 region1 与 region2 不同的区域
INTERSECT(1)最终区域为 region1 与 region2 相交的区域
UNION(2)最终区域为 region1 与 region2 组合的区域
XOR(3)最终区域为 region1 与 region2 相交之外的区域
REVERSE_DIFFERENCE(4)最终区域为 region2 与 region1 不同的区域
REPLACE(5)最终区域为 region2 的区域

Canvas05

完整示例

以下代码展示了各种裁剪模式的实际效果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
private void drawScene(Canvas canvas) {
    canvas.clipRect(0, 0, 100 * factor, 100 * factor);

    canvas.drawColor(Color.WHITE);

    mPaint.setColor(Color.RED);
    canvas.drawLine(0, 0, 100 * factor, 100 * factor, mPaint);

    mPaint.setColor(Color.GREEN);
    canvas.drawCircle(30 * factor, 70 * factor, 30 * factor, mPaint);

    mPaint.setColor(Color.BLUE);
    canvas.drawText("Clipping", 100 * factor, 30 * factor, mPaint);
}

@Override
protected void onDraw(Canvas canvas) {

    canvas.drawColor(Color.GRAY);

    canvas.save();
    canvas.translate(10 * factor, 10 * factor);
    drawScene(canvas);
    canvas.restore();

    canvas.save();
    canvas.translate(160 * factor, 10 * factor);
    // 剪切外圈
    canvas.clipRect(10 * factor, 10 * factor, 90 * factor, 90 * factor);
    // 中间挖空,保留 region1 与 region2 不同的区域
    canvas.clipRect(30 * factor, 30 * factor, 70 * factor, 70 * factor, Region.Op.DIFFERENCE);
    drawScene(canvas);
    canvas.restore();

    canvas.save();
    canvas.translate(10 * factor, 160 * factor);
    mPath.reset();
    // canvas.clipPath(mPath); // makes the clip empty
    mPath.addCircle(50 * factor, 50 * factor, 50 * factor, Path.Direction.CCW);
    canvas.clipPath(mPath, Region.Op.REPLACE);
    drawScene(canvas);
    canvas.restore();

    canvas.save();
    canvas.translate(160 * factor, 160 * factor);
    canvas.clipRect(0, 0, 60 * factor, 60 * factor);
    canvas.clipRect(40 * factor, 40 * factor, 100 * factor, 100 * factor, Region.Op.UNION);
    drawScene(canvas);
    canvas.restore();

    canvas.save();
    canvas.translate(10 * factor, 310 * factor);
    canvas.clipRect(0, 0, 60 * factor, 60 * factor);
    canvas.clipRect(40 * factor, 40 * factor, 100 * factor, 100 * factor, Region.Op.XOR);
    drawScene(canvas);
    canvas.restore();

    canvas.save();
    canvas.translate(160 * factor, 310 * factor);
    canvas.clipRect(0, 0, 60 * factor, 60 * factor);
    canvas.clipRect(40 * factor, 40 * factor, 100 * factor, 100 * factor,
            Region.Op.REVERSE_DIFFERENCE);
    drawScene(canvas);
    canvas.restore();
}

使用 canvas.save()canvas.restore() 可以保存和恢复 Canvas 状态,确保每次裁剪只影响当前绘制区域。

参考