方法介紹
- public boolean clipPath (Path path)
- public boolean clipPath (Path path, Region.Op op)
- public boolean clipRect (Rect rect)
- public boolean clipRect (Rect rect, Region.Op op)
這些方法都是用于在畫布上裁剪對應(yīng)的區(qū)域,只不過Rect是一個矩形捌蚊,Path是一個自定義路徑,還有另外一個參數(shù)是Region.Op ,它指定了不同的方式來剪切區(qū)域,為了更好的理解這些參數(shù),這里以上一次裁剪區(qū)域為A蚓聘,當(dāng)前裁剪區(qū)域為B做以表示:
- DIFFERENCE :裁剪差異部分,具體為A - A∩B
- INTERSECT:裁剪兩者相交的部分盟劫,A∩B
- UNION:裁剪兩者所有區(qū)域夜牡,A∪B
- XOR:exclusive OR的簡寫,翻譯為異或侣签,也就是兩者重疊部分為0塘装,不重疊部分為1,自然裁剪出來的就是不重疊的部分影所,也就是A∪B - A∩B
- REVERSE_DIFFERENCE:裁剪差異部分蹦肴,具體為B - A∩B
- REPLACE:B的裁剪區(qū)域會覆蓋A的區(qū)域,B
當(dāng)方法不指定裁剪模式時猴娩,默認為INTERSECT
說明:上一次裁剪區(qū)域指的是什么阴幌?指的就是在你調(diào)用最新的clipxxx之前所形成的區(qū)域,當(dāng)然clipxxx前也很有可能調(diào)用了多次clip胀溺,但你這次調(diào)用的clipxxx裂七,永遠相對的之前所形成的區(qū)域。
通常我們理解的clip(裁剪)仓坞,是對已經(jīng)存在的圖形進行clip的背零。但是,在Android上是對canvas(畫布)上進行clip的无埃,要在畫圖之前對canvas進行clip徙瓶,如果畫圖之后再對canvas進行clip不會影響到已經(jīng)畫好的圖形毛雇。一定要記住clip是針對canvas而非圖形。
由于本人當(dāng)時對這些方法及參數(shù)特別不理解侦镇,經(jīng)過查看多篇博客灵疮,再加上自己的測試,最終明白了壳繁,上面的參數(shù)解釋已經(jīng)是我自己所能表達的最清楚的程度了震捣。不過這里還是給出各種的測試效果,來更好的理解這些方法闹炉。
剪裁模式示例
初始代碼
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
RectF rectF = new RectF(100, 100, 400, 400);
canvas.drawColor(Color.BLUE);
canvas.drawRect(rectF, mPaint);
canvas.drawCircle(400, 250, 150, mPaint);
}
只是畫了一個300x300的紅色矩形蒿赢,和一個半徑為150,圓心在正方形右邊中點的紅色圓
效果如圖:
Region.Op.INTERSECT
測試代碼
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
RectF rectF = new RectF(100, 100, 400, 400);
canvas.drawColor(Color.BLUE);
canvas.drawRect(rectF, mPaint);
canvas.drawCircle(400, 250, 150, mPaint);
canvas.clipRect(rectF); // 1.
Path path = new Path();
path.addCircle(400, 250, 150, Path.Direction.CCW);
canvas.clipPath(path, Region.Op.INTERSECT); // 2.
canvas.drawColor(Color.GREEN); // 3.
}
- 第一次clipRect渣触,默認裁剪模式就是INTERSECT羡棵,對于它上一個裁剪區(qū)域就是整個Canvas,此時會裁剪出一個300x300的可用于繪制的矩形
- 第二次clipPath則是基于剛才裁剪出的矩形區(qū)域來說嗅钻,裁剪模式為INTERSECT皂冰,此時形成的區(qū)域就是下圖中綠色區(qū)域
-
通過繪制綠色可以看出剛才裁剪出來的區(qū)域
效果圖:
之后的測試都是通過改變注釋2代碼處模式進行,就不在貼代碼了
Region.Op.DIFFERENCE | Region.Op.REVERSE_DIFFERENCE | Region.Op.UNION | Region.Op.REPLACE | Region.Op.XOR |
---|---|---|---|---|
效果圖結(jié)合著參數(shù)解釋應(yīng)該就可以很好的理解了养篓。
Android9.0 Region.Op參數(shù)使用變更
Android 9.0 中如果在使用繪圖裁剪功能時設(shè)置了除 Region.Op.INTERSECT 或 Region.Op.DIFFERENCE 以外的類型秃流,就會拋出以下異常:
java.lang.IllegalArgumentException: Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed
具體原因是官方廢棄了那幾個具有 Region.Op 參數(shù)的裁剪方法,如 clipRect(@NonNull RectF rect, @NonNull Region.Op op) :
@Deprecated
public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) {
checkValidClipOp(op);
return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
op.nativeInt);
}
private static void checkValidClipOp(@NonNull Region.Op op) {
if (sCompatiblityVersion >= Build.VERSION_CODES.P
&& op != Region.Op.INTERSECT && op != Region.Op.DIFFERENCE) {
throw new IllegalArgumentException(
"Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed");
}
}
對于這個問題觉至,可以通過以下方法進行適配:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
canvas.clipPath(path);
} else {
canvas.clipPath(path, Region.Op.XOR);// REPLACE剔应、UNION 等類型
}