前言
根據Gcssloop所學習的自定義View整理與筆記。
一.填充模式
填充模式相關方法
方法 | 作用 |
---|---|
setFillType | 設置填充規則 |
getFillType | 獲取當前填充規則 |
isInverseFillType | 判斷是否是反向(INVERSE)規則 |
toggleInverseFillType | 切換填充規則(即原有規則與反向規則之間相互切換) |
填充規則有四種
模式 | 簡介 |
---|---|
EVEN_ODD | 奇偶規則 |
INVERSE_EVEN_ODD | 反奇偶規則 |
WINDING | 非零環繞數規則 |
INVERSE_WINDING | 反非零環繞數規則 |
** 1. 我們首先了解一下什么是奇偶規則。**
奇偶規則:如果是奇數,那么要被填充,如果是偶數則不填充。那么,怎么判斷奇數還是偶數呢?
從任意位置p作一條射線, 若與該射線相交的圖形邊的數目為奇數,需要被填充,否則是偶數,不被填充。
可以看出,
P1: 從P1發出一條射線,發現圖形與該射線相交邊數為0,偶數,不被填充。
P2: 從P2發出一條射線,發現圖形與該射線相交邊數為1,奇數,被填充。
P3: 從P3發出一條射線,發現圖形與該射線相交邊數為2,偶數,不被填充。
注意:奇偶規則與方向無關。
自然,反奇偶規則剛好與奇偶規則是相反的,不在贅述咯!
** 2. 非零環繞數規則揭秘**
假如一個點被從左到右跨過,計數器+1,從右到左跨過,計數器-1,最后,如果結果是0,那么不填充,如果是非零,那么填充。
注意:非零環繞數規則與方向有關哦,Path中任何線段都是有方向性的,這也是使用非零環繞數規則的基礎。
P1: 從P1點發出一條射線,沿射線防線移動,并沒有與邊相交點部分,環繞數為0,故不填充。
P2: 從P2點發出一條射線,沿射線方向移動,與圖形點左側邊相交,該邊從左到右穿過穿過射線,環繞數-1,最終環繞數為-1,故填充。
P3: 從P3點發出一條射線,沿射線方向移動,在第一個交點處,底邊從右到左穿過射線,環繞數+1,在第二個交點處,右側邊從左到右穿過射線,環繞數-1,最終環繞數為0,故不填充。
自然,反非零環繞數規則是與非零環繞數規則是相反的,也不在贅述咯!
接下來,就以非零環繞規則舉個demo吧
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.BLACK);
canvas.translate(300, 300);
Path path = new Path();
//內外同向
path.addRect(-200, -200, 200, 200, Path.Direction.CCW);
// path.addRect(-100, -100, 100, 100, Path.Direction.CCW);
//內外不同向
path.addRect(-100, -100, 100, 100, Path.Direction.CW);
//非零環繞數規則
path.setFillType(Path.FillType.WINDING);
canvas.drawPath(path, paint);
效果圖
二.布爾操作(API19)
1.Path的布爾運算邏輯
名稱 | 類比 | 說明 | 示意圖 |
---|---|---|---|
DIFFREENCE | 差集 | Path1中減去Path2后剩下的部分 | |
REVERSE_DIFFERENCE | 差集 | Path2中減去Path1后剩下的部分 | |
INTERSECT | 交集 | Path1與Path2相交的部分 | |
UNION | 并集 | 包含全部Path1和Path2 | |
XOR | 異或 | 包含Path1和Path2但不包含兩者相交的部分 |
2.布爾運算的方法
boolean op (Path path, Path.Op op)
boolean op (Path path1, Path path2, Path.Op op)
詳細說明的話,咱們得舉個小小例子
// 對 path1 和 path2 執行布爾運算,運算方式由第二個參數指定,運算結果存入到path1中。
path1.op(path2, Path.Op.DIFFERENCE);
// 對 path1 和 path2 執行布爾運算,運算方式由第三個參數指定,運算結果存入到path3中。
path3.op(path1, path2, Path.Op.DIFFERENCE)
來個太極demo:
canvas.drawColor(Color.YELLOW);
paint.setStyle(Paint.Style.FILL);
canvas.translate(300, 300);
//繪制一個白色的圓
paint.setColor(Color.WHITE);
canvas.drawCircle(0,0,200,paint);
//繪制太極
paint.setColor(Color.BLACK);
Path path1 = new Path();
Path path2 = new Path();
Path path3 = new Path();
Path path4 = new Path();
path1.addCircle(0, 0, 200, Path.Direction.CW);
path2.addRect(0, -200, 200, 200, Path.Direction.CW);
path3.addCircle(0, -100, 100, Path.Direction.CW);
path4.addCircle(0, 100, 100, Path.Direction.CW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
//path1減去path2,將結果存入path1
path1.op(path2, Path.Op.DIFFERENCE);
//包含全部path1和path3,將結果存入path1
path1.op(path3, Path.Op.UNION);
//path1減去path4,將結果存入path1
path1.op(path4, Path.Op.DIFFERENCE);
}
//繪制path1
canvas.drawPath(path1, paint);
小記:API<19的,要使用Region的op,Region我們將會放在自定義View-第十二步:Region講解。
三.計算邊界
void computeBounds (RectF bounds, boolean exact)
- bounds:測試結果會放入這個矩形
- exact :是否精確測量,這個參數作用目前已被廢棄,寫true即可
//----------
//上個demo的代碼
//在下邊加上如下代碼,測量path1的邊界
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.RED);
RectF rect = new RectF();
path1.computeBounds(rect, true);
canvas.drawRect(rect, paint);
四.重置路徑reset和rewind
|方法| 是否保留FillType設置| 是否保留原有數據結構|
|--------|--------|------|
|reset| 是 |否|
|rewind |否| 是|
這個兩個方法應該何時選擇呢?
選擇權重: FillType > 數據結構
因為“FillType”影響的是顯示效果,而“數據結構”影響的是重建速度。