Android Canvas API总结和使用方法

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//Canvas 操作函数 2015年5月15日 Android 4.4

int MATRIX_SAVE_FLAG = 0x01;
int CLIP_SAVE_FLAG = 0x02;
int HAS_ALPHA_LAYER_SAVE_FLAG = 0x04;
int FULL_COLOR_LAYER_SAVE_FLAG = 0x08;
int CLIP_TO_LAYER_SAVE_FLAG = 0x10;
int ALL_SAVE_FLAG = 0x1F; 
int DIRECTION_LTR = 0;

Canvas();
Canvas(Bitmap bitmap);

boolean isHardwareAccelerated();
void setBitmap(Bitmap bitmap);
boolean isOpaque();
int getWidth();
int getHeight();
int getDensity();
void setDensity(int density);
int getMaximumBitmapWidth();
int getMaximumBitmapHeight();

//图层保存与恢复操作
int save();   //保存当前图层
int save(int saveFlags);
//保存指定区域图层
//paint为要保存的画笔,restore()后可以用。一般为null
//saveFlags为要保存的内容
int saveLayer(RectF bounds, Paint paint, int saveFlags);  
int saveLayer(float left, float top, float right, float bottom, Paint paint, int saveFlags);
//保存指定区域图层,并修改其透明度
int saveLayerAlpha(RectF bounds, int alpha, int saveFlags);
int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int saveFlags);
void restore();         //恢复上一层图层
int getSaveCount();     //获得已只在的图层数量
void restoreToCount(int saveCount);  //恢复指定层的图层
//图层变换
void translate(float dx, float dy);
void scale(float sx, float sy);
void scale(float sx, float sy, float px, float py);
void rotate(float degrees);
void rotate(float degrees, float px, float py);
void skew(float sx, float sy);  //扭曲
void concat(Matrix matrix);  //Maxrix矩阵变换

void setMatrix(Matrix matrix);
void getMatrix(Matrix ctm);
Matrix getMatrix();
//裁剪
boolean clipRect(RectF rect, Region.Op op);
boolean clipRect(Rect rect, Region.Op op);
boolean clipRect(RectF rect);
boolean clipRect(Rect rect);
boolean clipRect(float left, float top, float right, float bottom, Region.Op op);
boolean clipRect(float left, float top, float right, float bottom);
boolean clipRect(int left, int top, int right, int bottom);
boolean clipPath(Path path, Region.Op op);
boolean clipPath(Path path);
boolean clipRegion(Region region, Region.Op op);
boolean clipRegion(Region region);

DrawFilter getDrawFilter();
void setDrawFilter(DrawFilter filter);
boolean quickReject(RectF rect, EdgeType type);
boolean quickReject(Path path, EdgeType type);
boolean quickReject(float left, float top, float right, float bottom, EdgeType type);
boolean getClipBounds(Rect bounds);
Rect getClipBounds();

//填充RGB
void drawRGB(int r, int g, int b);
void drawARGB(int a, int r, int g, int b);
//填充Color
void drawColor(int color);
void drawColor(int color, PorterDuff.Mode mode);
//指定画笔
void drawPaint(Paint paint);
//画点
void drawPoints(float[] pts, int offset, int count, Paint paint);
void drawPoints(float[] pts, Paint paint);
void drawPoint(float x, float y, Paint paint);
//画直线
void drawLine(float startX, float startY, float stopX, float stopY, Paint paint);
void drawLines(float[] pts, int offset, int count, Paint paint);  //pts数组里的每两个元素为一个点,每两个点画一条直线
void drawLines(float[] pts, Paint paint);
//画矩形
void drawRect(RectF rect, Paint paint);
void drawRect(Rect r, Paint paint);
void drawRect(float left, float top, float right, float bottom, Paint paint);
//画椭圆
void drawOval(RectF oval, Paint paint);
//画圆
void drawCircle(float cx, float cy, float radius, Paint paint);
//画弧,扇形
void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint);
//画圆角矩形
void drawRoundRect(RectF rect, float rx, float ry, Paint paint);
//画路径
void drawPath(Path path, Paint paint);
//画位图
void drawBitmap(Bitmap bitmap, float left, float top, Paint paint);
void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint);
void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint);
void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha,
void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, int height, boolean hasAlpha, Paint paint);
void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint);
void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, Paint paint);
//画顶点
void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, int indexOffset,
//画字
void drawText(char[] text, int index, int count, float x, float y, Paint paint);
void drawText(String text, float x, float y, Paint paint);
void drawText(String text, int start, int end, float x, float y, Paint paint);
void drawText(CharSequence text, int start, int end, float x, float y, Paint paint);
//绝对值画字
void drawPosText(char[] text, int index, int count, float[] pos, Paint paint);
void drawPosText(String text, float[] pos, Paint paint);
//根据路径画字
void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint);
void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint);
//画图片
void drawPicture(Picture picture);
void drawPicture(Picture picture, RectF dst);
void drawPicture(Picture picture, Rect dst);

Canvas draw系列函数用法示例:

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229

public class MyCanvasDrawView extends View {

private static final String TAG = null;

public MyCanvasDrawView(Context context) {
super(context);

}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//设置背景颜色
        canvas.drawColor(Color.WHITE);
//画弧
        drawMultArc(canvas);
//画路径和文字
        drawPathWithText(canvas);
//画直线
        drawLine(canvas);
//sample
        drawCompass(canvas, 10, 400);
    }

public void drawLine(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.YELLOW);
        paint.setStrokeWidth(5);
float offset = 150 / 6;
float leveOff = 150 / 4;
float[] pts = {600f + offset * 2, 400f - leveOff * 2, 750f - offset * 2, 400f - leveOff * 2,
                       600f + offset, 400f - leveOff , 750f - offset, 400f - leveOff,
                       600f, 400f , 750f, 400f
                      };
        canvas.drawLines(pts , paint);
    }

public void drawMultArc(Canvas canvas) {
        Paint[] mPaints;
boolean[] mUseCenters;
        RectF[] mRectF;

//边框的画笔
        Paint rectPaint = new Paint();
        rectPaint.setAntiAlias(true);
        rectPaint.setColor(Color.GRAY);
        rectPaint.setStyle(Paint.Style.STROKE);
        rectPaint.setStrokeWidth(5);

mUseCenters = new boolean[4];
        mPaints = new Paint[4];
        mRectF = new RectF[4];

initDrawMultArc(mPaints, mUseCenters);

_drawMultArc(canvas, mPaints, mUseCenters, mRectF, rectPaint);
    }

public void initDrawMultArc(Paint[] mPaints, boolean[] mUseCenters) {
//      1. 填充圆弧但不含圆心:
        mPaints[0] = new Paint();
        mPaints[0].setAntiAlias(true);
        mPaints[0].setStyle(Paint.Style.FILL);
        mPaints[0].setColor(0x88FF0000);
        mUseCenters[0] = false;

//      2. 填充圆弧带圆心(扇形)
        mPaints[1] = new Paint(mPaints[0]);
        mPaints[1].setColor(0x8800FF00);
        mUseCenters[1] = true;

//      3. 只绘圆周,不含圆心
        mPaints[2] = new Paint(mPaints[0]);
        mPaints[2].setStyle(Paint.Style.STROKE);
        mPaints[2].setStrokeWidth(4);
        mPaints[2].setColor(0x880000FF);
        mUseCenters[2] = false;

//      4. 只绘圆周,带圆心(扇形)
        mPaints[3] = new Paint(mPaints[2]);
        mPaints[3].setColor(0x88888888);
        mUseCenters[3] = true;
    }

public void _drawMultArc(Canvas canvas, Paint[] mPaints,
boolean[] mUseCenters, RectF[] mRectF, Paint rectPaint) {
int rectLeft = 10;
int rectTop = 50;
int width = 150;
int rectRight = rectLeft + width;
int rectBottom = rectTop + width;
int offest = rectLeft + width + 30 ;

//初始化弧形的区域,决定弧形的开关和位置
        for(int i = 0; i < 4; i++) {
            mRectF[i] = new RectF(rectLeft + i * offest, rectTop, rectRight + i * offest, rectBottom);
        }

Log.i(TAG, "mRectF[3] " + mRectF[3].left + " " + mRectF[3].bottom);

/**
         * 参数1:弧形的区域
         * 参数2:起始的角度
         * 参数3:弧形的角度
         * 参数4:是否有中心角度
         */
for ( int i = 0; i < 4; i++ ) {
            canvas.drawArc(mRectF[i], 30, 260, mUseCenters[i], mPaints[i]);
            canvas.drawRect(mRectF[i], rectPaint);
        }
    }

public void drawPathWithText(Canvas canvas) {
        Paint pathPaint = new Paint();
        pathPaint.setARGB(70, 238, 18, 137);
        pathPaint.setStyle(Paint.Style.FILL);
        pathPaint.setAntiAlias(true);
        pathPaint.setStrokeWidth(5);

Path path = new Path();

int pathStartX = 10;
int pathStartY = 250;
int length = 150;
//第一个三角形
        initPath(canvas, pathPaint, path, pathStartX, pathStartY, length);
        canvas.drawPath(path , pathPaint);

//清除path属性
        path.reset();
        pathPaint.setColor(Color.CYAN);
        pathPaint.setStyle(Paint.Style.STROKE);
        pathStartX = length + 50;
//第二个三角形
        initPath(canvas, pathPaint, path, pathStartX, pathStartY, length);
        canvas.drawPath(path , pathPaint);

//第三个图形
        path.reset();
        pathPaint.setColor(Color.DKGRAY);
        pathStartX = (length + 50) * 2;
//逆时针添加一个圆
        //最后一个参数指定构建方法,逆时针和顺时针,并不影响图形效果,但是会影响文字的构建顺序
        path.addCircle(pathStartX +  length / 2 , pathStartY +  length / 2, length / 2, Path.Direction.CCW);
        canvas.drawPath(path , pathPaint);

//设置字体属性
        pathPaint.setStrokeWidth(1);
        pathPaint.setTextSize(30);
        pathPaint.setTypeface(Typeface.SERIF);
        canvas.drawTextOnPath("Android Canvas&Paint", path, 10, 28, pathPaint);
        pathPaint.setTextSize(25);
        pathPaint.setStyle(Paint.Style.FILL);
        canvas.drawTextOnPath("Android", path, 10, -10, pathPaint);
    }

public void drawCompass(Canvas canvas, int startX, int startY) {

canvas.save();
        Paint paint;
        paint = new Paint(); //设置一个笔刷大小是3的黄色的画笔
        paint.setColor(Color.BLACK);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(3);

paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        canvas.translate(canvas.getWidth() / 2, 200); //移动画纸的坐标点:canvas.getWidth()/2, 200
        canvas.drawCircle(startX, startY, 100, paint); //画圆圈

//使用path绘制路径文字
        canvas.save();     //保存上面图层的信息
        canvas.translate(startX - 75, startY - 75);
        Path path = new Path();
        path.addArc(new RectF(0, 0, 150, 150), -145, 180);
        Paint citePaint = new Paint(paint);
        citePaint.setTextSize(14);
        citePaint.setStrokeWidth(1);
        citePaint.setColor(Color.GRAY);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawTextOnPath("my compass", path, 28, 0, citePaint);
        canvas.restore();     //恢复保存的图层

Paint tmpPaint = new Paint(paint); //小刻度画笔对象
        tmpPaint.setStrokeWidth(1);

float  y = startY - 100;
int count = 60; //总刻度数

for(int i = 0 ; i < count ; i++) {

if(i % 5 == 0) {
                canvas.drawLine(0f, y, 0f, y - 12f, paint);
                canvas.drawText(String.valueOf( i / 5 ), -4f, y - 20f, tmpPaint);

} else {
                canvas.drawLine(0f, y, 0f, y - 5f, tmpPaint);
            }
            canvas.rotate(360 / count, startX, startY); //旋转画纸
        }

//绘制中心点
        tmpPaint.setStyle(Paint.Style.FILL);
        tmpPaint.setColor(Color.GRAY);
        tmpPaint.setStrokeWidth(4);
        canvas.drawCircle(startX, startY, 7, tmpPaint);
        tmpPaint.setStyle(Paint.Style.FILL);
//绘制指针
        canvas.drawLine(startX, startY,  startX, startY - 65, paint);
        canvas.restore();
    }

public void initPath(Canvas canvas, Paint pathPaint, Path path,
int pathStartX, int pathStartY, int length) {
int pathX = pathStartX;
int pathY = pathStartY;
int pathLength = (int) Math.sqrt(Math.pow(length, 2) + Math.pow(length, 2));

//设置开始位置
        path.moveTo(pathX, pathY);
        pathX += (int) (pathLength * Math.cos(Math.toRadians(45)));
        pathY += (int) (pathLength * Math.sin(Math.toRadians(45)));
        path.lineTo(pathX, pathY);
//第二条线
        path.lineTo(pathStartX, pathY);
    }
}

Canvas 平移和形变
Canvas的平移和形变是画面的平移和形变,平衡和形变后会形成新的画布与之前的画面进行合并,并不影响原来的图像

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
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setStyle(Style.STROKE);
        paint.setStrokeWidth(3);

//平移
        canvas.save();
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.translate(25, 10);
        paint.setColor(Color.RED);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.restore();

//旋转
        canvas.save();  //如果不保存最原始的数据,新的平移会以上次的平移为基础
        canvas.translate(230, 0);
        paint.setColor(Color.GREEN);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);     
        canvas.rotate(30);
        paint.setColor(Color.RED);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.rotate(30);
        paint.setColor(Color.GRAY);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.restore();

//扭曲
        canvas.save();  
        canvas.translate(360, 0);
        paint.setColor(Color.GREEN);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        paint.setColor(Color.RED);
        canvas.skew(1.2f, 0);  //X轴倾斜,Y轴不变  
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.restore();

//缩放
        canvas.save();  
        canvas.translate(600, 0);
        paint.setStyle(Style.FILL);
        paint.setColor(Color.GREEN);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        paint.setColor(Color.RED);
        canvas.scale(0.5f, 0.8f);  //所有坐标按比例缩小
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.restore();
    }

Canvas 图层的保存与恢复
Canvas的图层保存与恢复是以栈的结构进行保存。遵循都先入后出的原则。通过sava()函数来把当前图层压栈。restore()函数来出栈上一次入栈的图层。也可能通多次调用save()来多次保存图层。restoreToCount()来恢复指定层数的图层。
saveFlags参数说明
1
2
3
4
5
6
7
8
9
10
11
12
/** 保存Matrix **/
public static final int MATRIX_SAVE_FLAG = 0x01;
/** 保存Clip **/
public static final int CLIP_SAVE_FLAG = 0x02;
/** 保存Alpha */
public static final int HAS_ALPHA_LAYER_SAVE_FLAG = 0x04;
/** 保存Color */
public static final int FULL_COLOR_LAYER_SAVE_FLAG = 0x08;
/** 保存整个Layer的Clip */
public static final int CLIP_TO_LAYER_SAVE_FLAG = 0x10;
/** 保存所有,很少用 */
public static final int ALL_SAVE_FLAG = 0x1F; 
saveLayerAlpha的使用


1
2
3
4
5
6
7
8
9
10
11
12
13
14
canvas.drawColor(Color.WHITE);

canvas.translate(10, 10);

mPaint.setColor(Color.RED);
canvas.drawCircle(75, 75, 75, mPaint);
//保存指定区域图层,并修改其透明度
canvas.saveLayerAlpha(0, 0, 200, 200, 0x55, LAYER_FLAGS);
mPaint.setColor(Color.BLUE);
//设置整个图层的透明度。在这里和上面的效果一样,但是要在setColor后面
//      mPaint.setAlpha(70);   
canvas.drawCircle(125, 125, 75, mPaint);

canvas.restore();

Canvas Region API总结
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
//Region API Android4.4 2015年5月16日
/**构造方法*/ 
Region();                   //创建一个空的区域 
Region(Region region);      //拷贝一个region
Region(Rect r);             //根据Rect创建
Region(int left, int top, int right, int bottom); //创建一个矩形的区域

/*设置函数方法*/
void setEmpty();
boolean set(Region region); //利用新的区域值来替换原来的区域
boolean set(Rect r);        //利用矩形所代表的区域替换原来的区域
boolean set(int left, int top, int right, int bottom); //根据矩形的两个点构造出矩形区域来替换原来的区域值
boolean setPath(Path path, Region clip);    //根据路径的区域与某区域的交集,构造出新区域

//判断
boolean isEmpty();
boolean isRect();
boolean isComplex();

//返回边界
Rect getBounds();
boolean getBounds(Rect r);
Path getBoundaryPath();
boolean getBoundaryPath(Path path);

//判断是否相交
boolean contains(int x, int y);     //是否有包含某点
boolean quickContains(Rect r);      //是否有包含矩区域
boolean quickContains(int left, int top, int right,  //根据两点是有否包含矩区域
boolean quickReject(Rect r);        //是否没包含矩形
boolean quickReject(int left, int top, int right, int bottom); //根据两点是否没包含矩区域
boolean quickReject(Region rgn);    //是否没和该矩阵相交

//平移和变换
void translate(int dx, int dy);
void translate(int dx, int dy, Region dst);
void scale(float scale);            //hide
void scale(float scale, Region dst);//hide

//组合
boolean union(Rect r);
boolean op(Rect r, Op op);
boolean op(int left, int top, int right, int bottom, Op op);
boolean op(Region region, Op op);
boolean op(Rect rect, Region region, Op op);
boolean op(Region region1, Region region2, Op op);
//组合方式:假设用region1  去组合region2   
public enum 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的区域  
 } 
int describeContents();
void writeToParcel(Parcel p, int flags);

Canvas Region用法示例
                       
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
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

Paint paint = new Paint();
    paint.setColor(Color.RED);
    paint.setStyle(Style.STROKE);
    paint.setStrokeWidth(2);
    Path path = new Path();

//总的显示荡然无存
    RectF rectf = new RectF(50, 50, 200, 500);
    path.addOval(rectf, Direction.CCW);

Region rgn = new Region();
//会显示的区域
    rgn.setPath(path, new Region(50, 50, 300, 600));

drawRegion(canvas, rgn, paint);
}

private void drawRegion(Canvas canvas, Region rgn, Paint paint) {
//把要显示的图像能过一个矩形组合来显示,放大显示出来的图像会发觉由很多小的矩形组成
    RegionIterator iter = new RegionIterator(rgn);
    Rect r = new Rect();

while (iter.next(r)) {
        canvas.drawRect(r, paint);
    }
}

Canvas clip系列函数用法示例
clip意为剪切,其实我觉得在这里意思为选中更为贴切,因为只有选中的区域才会操作有效。
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
public class MyClipView extends View {
    private Paint mPaint;
    private Path mPath;
    
    public MyClipView(Context context) {
        super(context);
        setFocusable(true);

mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(6);
        mPaint.setTextSize(16);
        mPaint.setTextAlign(Paint.Align.RIGHT);

mPath = new Path();
    }
    
    private void drawScene(Canvas canvas) {
        //下面的画图只在已被剪切的范围内有效
       canvas.clipRect(0, 0, 100, 100);

canvas.drawColor(Color.WHITE);

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

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

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

@Override protected void onDraw(Canvas canvas) {
//        canvas.drawColor(Color.GRAY);
        
        //没有被多次剪切的情况
        canvas.save();
        canvas.translate(10, 10);
        drawScene(canvas);
        canvas.restore();

canvas.save();
        canvas.translate(160, 10);
        canvas.clipRect(10, 10, 90, 90);
        canvas.clipRect(30, 30, 70, 70, Region.Op.DIFFERENCE);
        drawScene(canvas);
        canvas.restore();

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

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

canvas.save();
        canvas.translate(10, 310);
        canvas.clipRect(0, 0, 60, 60);
        canvas.clipRect(40, 40, 100, 100, Region.Op.INTERSECT);
        drawScene(canvas);
        canvas.restore();
        
        canvas.save();
        canvas.translate(160, 310);
        canvas.clipRect(0, 0, 60, 60);
        canvas.clipRect(40, 40, 100, 100, Region.Op.XOR);
        drawScene(canvas);
        canvas.restore();
      
        canvas.save();
        canvas.translate(10, 460);
        canvas.clipRect(0, 0, 60, 60);
        canvas.clipRect(40, 40, 100, 100, Region.Op.REVERSE_DIFFERENCE);
        drawScene(canvas);
        canvas.restore();

}
}

加入顶点 
参考文章:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html
http://blog.csdn.net/lonelyroamer/article/details/8349601
http://blog.csdn.net/harvic880925/article/details/38875149
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//Canvas 操作函数 2015年5月15日 Android 4.4

int MATRIX_SAVE_FLAG = 0x01;
int CLIP_SAVE_FLAG = 0x02;
int HAS_ALPHA_LAYER_SAVE_FLAG = 0x04;
int FULL_COLOR_LAYER_SAVE_FLAG = 0x08;
int CLIP_TO_LAYER_SAVE_FLAG = 0x10;
int ALL_SAVE_FLAG = 0x1F; 
int DIRECTION_LTR = 0;

Canvas();
Canvas(Bitmap bitmap);

boolean isHardwareAccelerated();
void setBitmap(Bitmap bitmap);
boolean isOpaque();
int getWidth();
int getHeight();
int getDensity();
void setDensity(int density);
int getMaximumBitmapWidth();
int getMaximumBitmapHeight();

//图层保存与恢复操作
int save();   //保存当前图层
int save(int saveFlags);
//保存指定区域图层
//paint为要保存的画笔,restore()后可以用。一般为null
//saveFlags为要保存的内容
int saveLayer(RectF bounds, Paint paint, int saveFlags);  
int saveLayer(float left, float top, float right, float bottom, Paint paint, int saveFlags);
//保存指定区域图层,并修改其透明度
int saveLayerAlpha(RectF bounds, int alpha, int saveFlags);
int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, int saveFlags);
void restore();         //恢复上一层图层
int getSaveCount();     //获得已只在的图层数量
void restoreToCount(int saveCount);  //恢复指定层的图层
//图层变换
void translate(float dx, float dy);
void scale(float sx, float sy);
void scale(float sx, float sy, float px, float py);
void rotate(float degrees);
void rotate(float degrees, float px, float py);
void skew(float sx, float sy);  //扭曲
void concat(Matrix matrix);  //Maxrix矩阵变换

void setMatrix(Matrix matrix);
void getMatrix(Matrix ctm);
Matrix getMatrix();
//裁剪
boolean clipRect(RectF rect, Region.Op op);
boolean clipRect(Rect rect, Region.Op op);
boolean clipRect(RectF rect);
boolean clipRect(Rect rect);
boolean clipRect(float left, float top, float right, float bottom, Region.Op op);
boolean clipRect(float left, float top, float right, float bottom);
boolean clipRect(int left, int top, int right, int bottom);
boolean clipPath(Path path, Region.Op op);
boolean clipPath(Path path);
boolean clipRegion(Region region, Region.Op op);
boolean clipRegion(Region region);

DrawFilter getDrawFilter();
void setDrawFilter(DrawFilter filter);
boolean quickReject(RectF rect, EdgeType type);
boolean quickReject(Path path, EdgeType type);
boolean quickReject(float left, float top, float right, float bottom, EdgeType type);
boolean getClipBounds(Rect bounds);
Rect getClipBounds();

//填充RGB
void drawRGB(int r, int g, int b);
void drawARGB(int a, int r, int g, int b);
//填充Color
void drawColor(int color);
void drawColor(int color, PorterDuff.Mode mode);
//指定画笔
void drawPaint(Paint paint);
//画点
void drawPoints(float[] pts, int offset, int count, Paint paint);
void drawPoints(float[] pts, Paint paint);
void drawPoint(float x, float y, Paint paint);
//画直线
void drawLine(float startX, float startY, float stopX, float stopY, Paint paint);
void drawLines(float[] pts, int offset, int count, Paint paint);  //pts数组里的每两个元素为一个点,每两个点画一条直线
void drawLines(float[] pts, Paint paint);
//画矩形
void drawRect(RectF rect, Paint paint);
void drawRect(Rect r, Paint paint);
void drawRect(float left, float top, float right, float bottom, Paint paint);
//画椭圆
void drawOval(RectF oval, Paint paint);
//画圆
void drawCircle(float cx, float cy, float radius, Paint paint);
//画弧,扇形
void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint);
//画圆角矩形
void drawRoundRect(RectF rect, float rx, float ry, Paint paint);
//画路径
void drawPath(Path path, Paint paint);
//画位图
void drawBitmap(Bitmap bitmap, float left, float top, Paint paint);
void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint);
void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint);
void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha,
void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, int height, boolean hasAlpha, Paint paint);
void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint);
void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, Paint paint);
//画顶点
void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, int indexOffset,
//画字
void drawText(char[] text, int index, int count, float x, float y, Paint paint);
void drawText(String text, float x, float y, Paint paint);
void drawText(String text, int start, int end, float x, float y, Paint paint);
void drawText(CharSequence text, int start, int end, float x, float y, Paint paint);
//绝对值画字
void drawPosText(char[] text, int index, int count, float[] pos, Paint paint);
void drawPosText(String text, float[] pos, Paint paint);
//根据路径画字
void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint);
void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint);
//画图片
void drawPicture(Picture picture);
void drawPicture(Picture picture, RectF dst);
void drawPicture(Picture picture, Rect dst);

Canvas draw系列函数用法示例:
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229

public class MyCanvasDrawView extends View {

private static final String TAG = null;

public MyCanvasDrawView(Context context) {
super(context);

}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//设置背景颜色
        canvas.drawColor(Color.WHITE);
//画弧
        drawMultArc(canvas);
//画路径和文字
        drawPathWithText(canvas);
//画直线
        drawLine(canvas);
//sample
        drawCompass(canvas, 10, 400);
    }

public void drawLine(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.YELLOW);
        paint.setStrokeWidth(5);
float offset = 150 / 6;
float leveOff = 150 / 4;
float[] pts = {600f + offset * 2, 400f - leveOff * 2, 750f - offset * 2, 400f - leveOff * 2,
                       600f + offset, 400f - leveOff , 750f - offset, 400f - leveOff,
                       600f, 400f , 750f, 400f
                      };
        canvas.drawLines(pts , paint);
    }

public void drawMultArc(Canvas canvas) {
        Paint[] mPaints;
boolean[] mUseCenters;
        RectF[] mRectF;

//边框的画笔
        Paint rectPaint = new Paint();
        rectPaint.setAntiAlias(true);
        rectPaint.setColor(Color.GRAY);
        rectPaint.setStyle(Paint.Style.STROKE);
        rectPaint.setStrokeWidth(5);

mUseCenters = new boolean[4];
        mPaints = new Paint[4];
        mRectF = new RectF[4];

initDrawMultArc(mPaints, mUseCenters);

_drawMultArc(canvas, mPaints, mUseCenters, mRectF, rectPaint);
    }

public void initDrawMultArc(Paint[] mPaints, boolean[] mUseCenters) {
//      1. 填充圆弧但不含圆心:
        mPaints[0] = new Paint();
        mPaints[0].setAntiAlias(true);
        mPaints[0].setStyle(Paint.Style.FILL);
        mPaints[0].setColor(0x88FF0000);
        mUseCenters[0] = false;

//      2. 填充圆弧带圆心(扇形)
        mPaints[1] = new Paint(mPaints[0]);
        mPaints[1].setColor(0x8800FF00);
        mUseCenters[1] = true;

//      3. 只绘圆周,不含圆心
        mPaints[2] = new Paint(mPaints[0]);
        mPaints[2].setStyle(Paint.Style.STROKE);
        mPaints[2].setStrokeWidth(4);
        mPaints[2].setColor(0x880000FF);
        mUseCenters[2] = false;

//      4. 只绘圆周,带圆心(扇形)
        mPaints[3] = new Paint(mPaints[2]);
        mPaints[3].setColor(0x88888888);
        mUseCenters[3] = true;
    }

public void _drawMultArc(Canvas canvas, Paint[] mPaints,
boolean[] mUseCenters, RectF[] mRectF, Paint rectPaint) {
int rectLeft = 10;
int rectTop = 50;
int width = 150;
int rectRight = rectLeft + width;
int rectBottom = rectTop + width;
int offest = rectLeft + width + 30 ;

//初始化弧形的区域,决定弧形的开关和位置
        for(int i = 0; i < 4; i++) {
            mRectF[i] = new RectF(rectLeft + i * offest, rectTop, rectRight + i * offest, rectBottom);
        }

Log.i(TAG, "mRectF[3] " + mRectF[3].left + " " + mRectF[3].bottom);

/**
         * 参数1:弧形的区域
         * 参数2:起始的角度
         * 参数3:弧形的角度
         * 参数4:是否有中心角度
         */
for ( int i = 0; i < 4; i++ ) {
            canvas.drawArc(mRectF[i], 30, 260, mUseCenters[i], mPaints[i]);
            canvas.drawRect(mRectF[i], rectPaint);
        }
    }

public void drawPathWithText(Canvas canvas) {
        Paint pathPaint = new Paint();
        pathPaint.setARGB(70, 238, 18, 137);
        pathPaint.setStyle(Paint.Style.FILL);
        pathPaint.setAntiAlias(true);
        pathPaint.setStrokeWidth(5);

Path path = new Path();

int pathStartX = 10;
int pathStartY = 250;
int length = 150;
//第一个三角形
        initPath(canvas, pathPaint, path, pathStartX, pathStartY, length);
        canvas.drawPath(path , pathPaint);

//清除path属性
        path.reset();
        pathPaint.setColor(Color.CYAN);
        pathPaint.setStyle(Paint.Style.STROKE);
        pathStartX = length + 50;
//第二个三角形
        initPath(canvas, pathPaint, path, pathStartX, pathStartY, length);
        canvas.drawPath(path , pathPaint);

//第三个图形
        path.reset();
        pathPaint.setColor(Color.DKGRAY);
        pathStartX = (length + 50) * 2;
//逆时针添加一个圆
        //最后一个参数指定构建方法,逆时针和顺时针,并不影响图形效果,但是会影响文字的构建顺序
        path.addCircle(pathStartX +  length / 2 , pathStartY +  length / 2, length / 2, Path.Direction.CCW);
        canvas.drawPath(path , pathPaint);

//设置字体属性
        pathPaint.setStrokeWidth(1);
        pathPaint.setTextSize(30);
        pathPaint.setTypeface(Typeface.SERIF);
        canvas.drawTextOnPath("Android Canvas&Paint", path, 10, 28, pathPaint);
        pathPaint.setTextSize(25);
        pathPaint.setStyle(Paint.Style.FILL);
        canvas.drawTextOnPath("Android", path, 10, -10, pathPaint);
    }

public void drawCompass(Canvas canvas, int startX, int startY) {

canvas.save();
        Paint paint;
        paint = new Paint(); //设置一个笔刷大小是3的黄色的画笔
        paint.setColor(Color.BLACK);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeWidth(3);

paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        canvas.translate(canvas.getWidth() / 2, 200); //移动画纸的坐标点:canvas.getWidth()/2, 200
        canvas.drawCircle(startX, startY, 100, paint); //画圆圈

//使用path绘制路径文字
        canvas.save();     //保存上面图层的信息
        canvas.translate(startX - 75, startY - 75);
        Path path = new Path();
        path.addArc(new RectF(0, 0, 150, 150), -145, 180);
        Paint citePaint = new Paint(paint);
        citePaint.setTextSize(14);
        citePaint.setStrokeWidth(1);
        citePaint.setColor(Color.GRAY);
        paint.setStyle(Paint.Style.FILL);
        canvas.drawTextOnPath("my compass", path, 28, 0, citePaint);
        canvas.restore();     //恢复保存的图层

Paint tmpPaint = new Paint(paint); //小刻度画笔对象
        tmpPaint.setStrokeWidth(1);

float  y = startY - 100;
int count = 60; //总刻度数

for(int i = 0 ; i < count ; i++) {

if(i % 5 == 0) {
                canvas.drawLine(0f, y, 0f, y - 12f, paint);
                canvas.drawText(String.valueOf( i / 5 ), -4f, y - 20f, tmpPaint);

} else {
                canvas.drawLine(0f, y, 0f, y - 5f, tmpPaint);
            }
            canvas.rotate(360 / count, startX, startY); //旋转画纸
        }

//绘制中心点
        tmpPaint.setStyle(Paint.Style.FILL);
        tmpPaint.setColor(Color.GRAY);
        tmpPaint.setStrokeWidth(4);
        canvas.drawCircle(startX, startY, 7, tmpPaint);
        tmpPaint.setStyle(Paint.Style.FILL);
//绘制指针
        canvas.drawLine(startX, startY,  startX, startY - 65, paint);
        canvas.restore();
    }

public void initPath(Canvas canvas, Paint pathPaint, Path path,
int pathStartX, int pathStartY, int length) {
int pathX = pathStartX;
int pathY = pathStartY;
int pathLength = (int) Math.sqrt(Math.pow(length, 2) + Math.pow(length, 2));

//设置开始位置
        path.moveTo(pathX, pathY);
        pathX += (int) (pathLength * Math.cos(Math.toRadians(45)));
        pathY += (int) (pathLength * Math.sin(Math.toRadians(45)));
        path.lineTo(pathX, pathY);
//第二条线
        path.lineTo(pathStartX, pathY);
    }
}

Canvas 平移和形变
Canvas的平移和形变是画面的平移和形变,平衡和形变后会形成新的画布与之前的画面进行合并,并不影响原来的图像
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
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setColor(Color.GREEN);
        paint.setStyle(Style.STROKE);
        paint.setStrokeWidth(3);

//平移
        canvas.save();
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.translate(25, 10);
        paint.setColor(Color.RED);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.restore();

//旋转
        canvas.save();  //如果不保存最原始的数据,新的平移会以上次的平移为基础
        canvas.translate(230, 0);
        paint.setColor(Color.GREEN);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);     
        canvas.rotate(30);
        paint.setColor(Color.RED);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.rotate(30);
        paint.setColor(Color.GRAY);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.restore();

//扭曲
        canvas.save();  
        canvas.translate(360, 0);
        paint.setColor(Color.GREEN);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        paint.setColor(Color.RED);
        canvas.skew(1.2f, 0);  //X轴倾斜,Y轴不变  
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.restore();

//缩放
        canvas.save();  
        canvas.translate(600, 0);
        paint.setStyle(Style.FILL);
        paint.setColor(Color.GREEN);
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        paint.setColor(Color.RED);
        canvas.scale(0.5f, 0.8f);  //所有坐标按比例缩小
        canvas.drawRect(new Rect(10, 10, 100, 100), paint);
        canvas.restore();
    }

Canvas 图层的保存与恢复、
Canvas的图层保存与恢复是以栈的结构进行保存。遵循都先入后出的原则。通过sava()函数来把当前图层压栈。restore()函数来出栈上一次入栈的图层。也可能通多次调用save()来多次保存图层。restoreToCount()来恢复指定层数的图层。
saveFlags参数说明
1
2
3
4
5
6
7
8
9
10
11
12
/** 保存Matrix **/
public static final int MATRIX_SAVE_FLAG = 0x01;
/** 保存Clip **/
public static final int CLIP_SAVE_FLAG = 0x02;
/** 保存Alpha */
public static final int HAS_ALPHA_LAYER_SAVE_FLAG = 0x04;
/** 保存Color */
public static final int FULL_COLOR_LAYER_SAVE_FLAG = 0x08;
/** 保存整个Layer的Clip */
public static final int CLIP_TO_LAYER_SAVE_FLAG = 0x10;
/** 保存所有,很少用 */
public static final int ALL_SAVE_FLAG = 0x1F; 
saveLayerAlpha的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
canvas.drawColor(Color.WHITE);

canvas.translate(10, 10);

mPaint.setColor(Color.RED);
canvas.drawCircle(75, 75, 75, mPaint);
//保存指定区域图层,并修改其透明度
canvas.saveLayerAlpha(0, 0, 200, 200, 0x55, LAYER_FLAGS);
mPaint.setColor(Color.BLUE);
//设置整个图层的透明度。在这里和上面的效果一样,但是要在setColor后面
//      mPaint.setAlpha(70);   
canvas.drawCircle(125, 125, 75, mPaint);

canvas.restore();

Canvas Region API总结
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
//Region API Android4.4 2015年5月16日
/**构造方法*/ 
Region();                   //创建一个空的区域 
Region(Region region);      //拷贝一个region
Region(Rect r);             //根据Rect创建
Region(int left, int top, int right, int bottom); //创建一个矩形的区域

/*设置函数方法*/
void setEmpty();
boolean set(Region region); //利用新的区域值来替换原来的区域
boolean set(Rect r);        //利用矩形所代表的区域替换原来的区域
boolean set(int left, int top, int right, int bottom); //根据矩形的两个点构造出矩形区域来替换原来的区域值
boolean setPath(Path path, Region clip);    //根据路径的区域与某区域的交集,构造出新区域

//判断
boolean isEmpty();
boolean isRect();
boolean isComplex();

//返回边界
Rect getBounds();
boolean getBounds(Rect r);
Path getBoundaryPath();
boolean getBoundaryPath(Path path);

//判断是否相交
boolean contains(int x, int y);     //是否有包含某点
boolean quickContains(Rect r);      //是否有包含矩区域
boolean quickContains(int left, int top, int right,  //根据两点是有否包含矩区域
boolean quickReject(Rect r);        //是否没包含矩形
boolean quickReject(int left, int top, int right, int bottom); //根据两点是否没包含矩区域
boolean quickReject(Region rgn);    //是否没和该矩阵相交

//平移和变换
void translate(int dx, int dy);
void translate(int dx, int dy, Region dst);
void scale(float scale);            //hide
void scale(float scale, Region dst);//hide

//组合
boolean union(Rect r);
boolean op(Rect r, Op op);
boolean op(int left, int top, int right, int bottom, Op op);
boolean op(Region region, Op op);
boolean op(Rect rect, Region region, Op op);
boolean op(Region region1, Region region2, Op op);
//组合方式:假设用region1  去组合region2   
public enum 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的区域  
 } 
int describeContents();
void writeToParcel(Parcel p, int flags);

Canvas Region用法示例
      
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
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

Paint paint = new Paint();
    paint.setColor(Color.RED);
    paint.setStyle(Style.STROKE);
    paint.setStrokeWidth(2);
    Path path = new Path();

//总的显示荡然无存
    RectF rectf = new RectF(50, 50, 200, 500);
    path.addOval(rectf, Direction.CCW);

Region rgn = new Region();
//会显示的区域
    rgn.setPath(path, new Region(50, 50, 300, 600));

drawRegion(canvas, rgn, paint);
}

private void drawRegion(Canvas canvas, Region rgn, Paint paint) {
//把要显示的图像能过一个矩形组合来显示,放大显示出来的图像会发觉由很多小的矩形组成
    RegionIterator iter = new RegionIterator(rgn);
    Rect r = new Rect();

while (iter.next(r)) {
        canvas.drawRect(r, paint);
    }
}

Canvas clip系列函数用法示例
clip意为剪切,其实我觉得在这里意思为选中更为贴切,因为只有选中的区域才会操作有效。
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
public class MyClipView extends View {
    private Paint mPaint;
    private Path mPath;
    
    public MyClipView(Context context) {
        super(context);
        setFocusable(true);

mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(6);
        mPaint.setTextSize(16);
        mPaint.setTextAlign(Paint.Align.RIGHT);

mPath = new Path();
    }
    
    private void drawScene(Canvas canvas) {
        //下面的画图只在已被剪切的范围内有效
       canvas.clipRect(0, 0, 100, 100);

canvas.drawColor(Color.WHITE);

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

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

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

@Override protected void onDraw(Canvas canvas) {
//        canvas.drawColor(Color.GRAY);
        
        //没有被多次剪切的情况
        canvas.save();
        canvas.translate(10, 10);
        drawScene(canvas);
        canvas.restore();

canvas.save();
        canvas.translate(160, 10);
        canvas.clipRect(10, 10, 90, 90);
        canvas.clipRect(30, 30, 70, 70, Region.Op.DIFFERENCE);
        drawScene(canvas);
        canvas.restore();

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

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

canvas.save();
        canvas.translate(10, 310);
        canvas.clipRect(0, 0, 60, 60);
        canvas.clipRect(40, 40, 100, 100, Region.Op.INTERSECT);
        drawScene(canvas);
        canvas.restore();
        
        canvas.save();
        canvas.translate(160, 310);
        canvas.clipRect(0, 0, 60, 60);
        canvas.clipRect(40, 40, 100, 100, Region.Op.XOR);
        drawScene(canvas);
        canvas.restore();
      
        canvas.save();
        canvas.translate(10, 460);
        canvas.clipRect(0, 0, 60, 60);
        canvas.clipRect(40, 40, 100, 100, Region.Op.REVERSE_DIFFERENCE);
        drawScene(canvas);
        canvas.restore();

}
}

加入顶点 
参考文章:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html
http://blog.csdn.net/lonelyroamer/article/details/8349601
http://blog.csdn.net/harvic880925/article/details/38875149

Android Canvas API总结和使用方法相关推荐

  1. clear html5代码,用HTML5 Canvas API中的clearRect()方法实现橡皮擦功能

    在现实世界中,我们使用画笔在画板上进行绘画:在html5 canvas中,我们同样可以使用canvas的画笔--CanvasRenderingContext2D对象在canvas上进行绘画.众所周知, ...

  2. Android复习14【高级编程:推荐网址、抠图片上的某一角下来、Bitmap引起的OOM问题、三个绘图工具类详解、画线条、Canvas API详解(平移、旋转、缩放、倾斜)、矩阵详解】

    目   录 推荐网址 抠图片上的某一角下来 8.2.2 Bitmap引起的OOM问题 8.3.1 三个绘图工具类详解 画线条 8.3.16 Canvas API详解(Part 1) 1.transla ...

  3. Android 中的 Canvas API

    使用 Android Widget 组中不存在的自定义 UI 元素并想知道它是如何制作的? 这是 Android 中存在的 Canvas API 的魔力.我认为画布这个名字本身就定义了它是艺术家的游乐 ...

  4. Android基础入门教程——8.3.18 Canvas API详解(Part 3)Matrix和drawBitmapMash

    Android基础入门教程--8.3.18 Canvas API详解(Part 3)Matrix和drawBitmapMash 标签(空格分隔): Android基础入门教程 本节引言: 在Canva ...

  5. 介绍Android中的Paint和Canvas的概念和使用方法

    下面开始正式介绍内容 一.介绍Android中的Paint和Canvas的概念和使用方法 Android中的Paint和Canvas的概念是很简单的,就是我们用画笔在画布上进行绘制没什么难度的,我们只 ...

  6. 【Android 内存优化】Android 原生 API 图片压缩原理 ( Bitmap_compress 方法解析 | Skia 二维图形库 | libjpeg 函数库 | libpng 函数库 )

    文章目录 一. 图片质量压缩方法 二. Skia 二维图形库 三. libjpeg.libpng 函数库引入 在博客 [Android 内存优化]图片文件压缩 ( Android 原生 API 提供的 ...

  7. 【Android 内存优化】Android 原生 API 图片压缩原理 ( 图片质量压缩方法 | 查找 Java 源码中的 native 方法对应的 C++ 源码 )

    文章目录 一. 图片质量压缩方法 二. 查找对应的 Native 方法源码 三. 分析 Bitmap.cpp 中动态注册 Native 方法 在博客 [Android 内存优化]图片文件压缩 ( An ...

  8. (四)Canvas API方法和属性汇总

    canvas主要属性和方法 方法 描述 save() 保存当前环境的状态 restore() 返回之前保存过的路径状态和属性 createEvent()   getContext() 返回一个对象,指 ...

  9. android 画布控件,Android canvas画图操作之切割画布实现方法(clipRect)

    本文实例讲述了Android canvas画图操作之切割画布实现方法.分享给大家供大家参考,具体如下: android切割画布的历程不算很难,可是理解起来也比较麻烦,这里写一下我的理解 但是不一定正确 ...

  10. 每日一句api Android,金山每日一句 API 接口调用接入方法

    原标题:金山每日一句 API 接口调用接入方法 金山每日一句 API 大家都听说过吧,金山每日一句 API 每次刷新网页都会带来一个新的语句,现在盒子部落公布金山每日一句 API 接口,可以直接在自己 ...

最新文章

  1. Android框架之路——EventBus的使用
  2. Swift2.0 中的String(一):常用属性
  3. Mybatis入门学习---创建第一个Mybatis程序
  4. 计算机教室内网连接不了,校园网登陆不了内网怎么办?校园网登陆不了内网的解决方法...
  5. VirtualBox下Ubuntu利用桥接方式上网
  6. GetWeApp聊天室 代码(微信小程序)
  7. useEffect和useLayoutEffect区别
  8. ubuntu proxy
  9. [转]通过崩溃地址找错误行数之Delphi版
  10. pdf文档怎么删除内容页面
  11. EXCEL 常用的宏代码大全
  12. 中国省份城市数据库表
  13. 知识笔记 - 平头哥ratel安卓Hook框架的安装与简单使用
  14. 学习SEO就到SEOWHY,SEO十万个为什…
  15. 计算机教研评课记录,信息技术2.0 | 评课磨课共成长 信息技术促进步 ——东光县第二实验小学信息技术2.0数学组 课例研讨...
  16. ClickHouse技术分享PPT
  17. 使用Wechaty搭建微信文件日程匣子
  18. shell脚本遍历目录下的所有文件并进行操作
  19. jquery.slides.js 幻灯片脚本使用方法
  20. java注解看这一篇就够了

热门文章

  1. matlab中如何画柱状图,matlab如何画柱状图?matlab绘制柱状图教程
  2. 使用html语言编写收银系统,蓝色简洁样式html5店铺收银系统网页模板
  3. Unity网络编程一: 基于Socket搭建一个服务器
  4. CAD软件绘图如何提高效率 (下)
  5. 《Java学习笔记1》
  6. PS视频降噪去噪点插件;DeNoise英文可选 支持CS6- cc2019
  7. 超好用的自动化测试工具——Python脚本
  8. 命令行查看文件夹大小
  9. 软件开发成本工作量估算
  10. 命令创建vue项目工程