Canvas中clipRect换怖、clipPath 剪切方法理解

方法介紹

  • 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 等類型
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末睡腿,一起剝皮案震驚了整個濱河市语御,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌席怪,老刑警劉巖应闯,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異挂捻,居然都是意外死亡碉纺,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門刻撒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來骨田,“玉大人,你說我怎么就攤上這事声怔√停” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵醋火,是天一觀的道長悠汽。 經(jīng)常有香客問我箱吕,道長,這世上最難降的妖魔是什么柿冲? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任茬高,我火速辦了婚禮,結(jié)果婚禮上假抄,老公的妹妹穿的比我還像新娘怎栽。我一直安慰自己,他們只是感情好宿饱,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布婚瓜。 她就那樣靜靜地躺著,像睡著了一般刑棵。 火紅的嫁衣襯著肌膚如雪巴刻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天蛉签,我揣著相機與錄音胡陪,去河邊找鬼。 笑死碍舍,一個胖子當(dāng)著我的面吹牛柠座,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播片橡,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼妈经,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了捧书?” 一聲冷哼從身側(cè)響起吹泡,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎经瓷,沒想到半個月后爆哑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡舆吮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年揭朝,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片色冀。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡潭袱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锋恬,到底是詐尸還是另有隱情屯换,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布伶氢,位于F島的核電站趟径,受9級特大地震影響瘪吏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜗巧,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一掌眠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧幕屹,春花似錦蓝丙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至说敏,卻和暖如春鸥跟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盔沫。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工医咨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人架诞。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓拟淮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谴忧。 傳聞我的和親對象是個殘疾皇子很泊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容