版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。
系列教程:Android開發(fā)之從零開始系列大家要是看到有錯(cuò)誤的地方或者有啥好的建議,歡迎留言評(píng)論
前言:開發(fā)過程中很容易忘記一些API的使用方法,網(wǎng)上搜索或者在源碼里找也很難短時(shí)間內(nèi)篩選出自己需要的,遂自己將這些知識(shí)總結(jié)一番
常用API解析與示例
一、xxxTo方法
Path類中提供了一套xxxTo方法,其作用是從起點(diǎn)到終點(diǎn)移動(dòng)path畫筆并繪制線(moveTo方法只移動(dòng)path畫筆不繪制線),線有直線和曲線。方法匯總?cè)缦卤硭?/p>
| 方法名 | 參數(shù)解析 |
|---|---|
| lineTo(float x, float y) | 繪制直線,x:終點(diǎn)x坐標(biāo)值,y:終點(diǎn)y坐標(biāo)值 |
| moveTo(float x, float y) | 移動(dòng)畫筆,x:終點(diǎn)x坐標(biāo)值,y:終點(diǎn)y坐標(biāo)值 |
| arcTo(RectF oval, float startAngle, float sweepAngle) | 繪制圓弧,oval:圓弧矩形區(qū)域,startAngle:起始角度,sweepAngle:圓弧旋轉(zhuǎn)的角度 |
| arcTo(RectF oval, float startAngle, float sweepAngle,boolean forceMoveTo) | 繪制圓弧,oval:圓弧矩形區(qū)域,startAngle:起始角度,sweepAngle:圓弧旋轉(zhuǎn)的角度,forceMoveTo:是否在繪制圓弧前移動(dòng)(moveTo)path畫筆位置 |
| arcTo(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean forceMoveTo) | 繪制圓弧,left、top、right、bottom組成圓弧矩形區(qū)域,startAngle:起始角度,sweepAngle:圓弧旋轉(zhuǎn)的角度,forceMoveTo:是否在繪制圓弧前移動(dòng)(moveTo)path畫筆位置 |
| quadTo(float x1, float y1, float x2, float y2) | 繪制二階貝塞爾曲線,控制點(diǎn)坐標(biāo):(x1,y1),終點(diǎn)坐標(biāo):(x2,y2) |
| cubicTo(float x1, float y1, float x2, float y2,float x3, float y3) | 繪制三階貝塞爾曲線,其中控制點(diǎn)1坐標(biāo)為(x1,y1),控制點(diǎn)2坐標(biāo)為(x2,y2),終點(diǎn)坐標(biāo)為(x3,y3) |
1.lineTo(float x, float y)
繪制直線,從當(dāng)前畫筆位置出發(fā),連接終點(diǎn)(x,y),示例如下
示例如下
path.lineTo(300,300);
canvas.drawPath(path,paint);

2.moveTo(float x, float y)
移動(dòng)畫筆,從當(dāng)前畫筆位置移動(dòng)到終點(diǎn)(x,y)
示例如下
path.moveTo(100,100);
path.lineTo(300,300);
canvas.drawPath(path,paint);

3.arcTo(RectF oval, float startAngle, float sweepAngle)
繪制圓弧,從當(dāng)前畫筆位置出發(fā),連線到內(nèi)切矩形區(qū)域oval的圓弧的起始角度startAngle位置(X軸正方向?yàn)?°),順時(shí)針旋轉(zhuǎn)繪制圓弧,旋轉(zhuǎn)度數(shù)為sweepAngle(sweepAngle為負(fù)時(shí)則逆時(shí)針旋轉(zhuǎn))
示例如下
RectF rectF = new RectF(100,100,300,400);
path.arcTo(rectF,0,180);
canvas.drawPath(path,pathPaint);

arcTo(RectF oval, float startAngle, float sweepAngle,boolean forceMoveTo)
繪制圓弧,若forceMoveTo為false,則用法和arcTo(RectF oval, float startAngle, float sweepAngle)一樣,繪制圓弧之前不會(huì)移動(dòng)(moveTo)path畫筆位置。若為true,先強(qiáng)制調(diào)用moveTo移動(dòng)path畫筆至圓弧起點(diǎn),再繪制圓弧。ps:如果調(diào)用arcTo(RectF oval, float startAngle, float sweepAngle,boolean forceMoveTo)方法之前沒有對(duì)path進(jìn)行任何操作,則forceMoveTo設(shè)置true或false效果都和設(shè)置true一樣
示例如下,注意對(duì)比之間的差異
RectF rectF = new RectF(100,100,300,400);
path.moveTo(100,100);
path.arcTo(rectF,0,180,false);
path.close();
canvas.drawPath(path,pathPaint);

RectF rectF = new RectF(100,100,300,400);
path.moveTo(100,100);
path.arcTo(rectF,0,180,true);
path.close();
canvas.drawPath(path,pathPaint);

RectF rectF = new RectF(100,100,300,400);
path.arcTo(rectF,0,180,false);
path.close();
canvas.drawPath(path,pathPaint);

arcTo(float left, float top, float right, float bottom, float startAngle,float sweepAngle, boolean forceMoveTo)
與arcTo(RectF oval, float startAngle, float sweepAngle,boolean forceMoveTo)用法一樣
4.quadTo(float x1, float y1, float x2, float y2)
從path畫筆當(dāng)前位置出發(fā),以(x?,y?)為控制點(diǎn),向終點(diǎn)(x?,y?)繪制一條二階貝塞爾曲線
示例如下
path.moveTo(100,100);
path.quadTo(200,0,400,100);
canvas.drawPath(path,pathPaint);

5.cubicTo(float x1, float y1, float x2, float y2,float x3, float y3)
從path畫筆當(dāng)前位置出發(fā),以(x1,y1)為控制點(diǎn)1,以(x2,y2)為控制點(diǎn)2,向終點(diǎn)(x3,y3)繪制一條三階貝塞爾曲線
簡(jiǎn)單示例如下
path.moveTo(100,100);
path.cubicTo(200,0,300,90,500,100);
canvas.drawPath(path,pathPaint);

圓形其實(shí)也是由四段三階貝塞爾曲線組成,我們繪制其中兩段看看效果即可,示例如下
path.moveTo(300,200);
path.cubicTo(300,200+100*0.551915024494f,200+100*0.551915024494f,300,200,300);
path.moveTo(200-20,300);
path.cubicTo(200-100*0.551915024494f-20,300,100-20,200+100*0.551915024494f,100-20,200);
canvas.drawPath(path,pathPaint);

二、rXxxTo方法

rXxxTo方法的r意思是relative,即相對(duì)的意思,方法有四個(gè),如上圖所示,其功能與對(duì)應(yīng)的xxxTo方法一樣,區(qū)別在于rXxxTo方法在繪制Path時(shí)是以當(dāng)前path畫筆位置為坐標(biāo)原點(diǎn),即相對(duì)于path畫筆位置進(jìn)行繪制,而xxxTo方法的坐標(biāo)原點(diǎn)則與當(dāng)前canvas坐標(biāo)原點(diǎn)一致。例如,我們使用xxxTo方法
path.moveTo(100,100);
path.lineTo(300,300);
canvas.drawPath(path, pathPaint);
上述代碼是從(100,100)到(300,300)繪制一條直線,那么如果用rXxxTo方法,相對(duì)(100,100)這個(gè)點(diǎn)繪制直線,則終點(diǎn)應(yīng)為(300-100,300-100),即終點(diǎn)設(shè)為(200,200),如下所示
path.moveTo(100,100);
path.rLineTo(200,200);
canvas.drawPath(path, pathPaint);
效果都是一樣的

三、addXxx方法
Path類中還提供了一套addXxx方法,字面理解就是添加一段相應(yīng)的線,線可以是曲線、完整的圓形、矩形等,甚至可以是另一組Path的線。所謂添加的意思,我個(gè)人理解就是在繪制這段線前,移動(dòng)(moveTo)path畫筆位置到線的起始位置,然后再繪制線,也就是說添加的這段線,與之前繪制的Path是分離的(除非后繪制的這段線的起始點(diǎn)與之前Path的終點(diǎn)一致)。方法匯總?cè)缦卤硭?/p>
| 方法名 | 參數(shù)解析 |
|---|---|
| addArc(RectF oval, float startAngle, float sweepAngle) | 添加圓弧,oval:圓弧矩形區(qū)域,startAngle:起始角度,sweepAngle:圓弧旋轉(zhuǎn)的角度 |
| addArc(float left, float top, float right, float bottom, float startAngle,float sweepAngle) | 添加圓弧,left、top、right、bottom組成圓弧矩形區(qū)域,startAngle:起始角度,sweepAngle:圓弧旋轉(zhuǎn)的角度。ps:此方法在API 19以上有效 |
| addCircle(float x, float y, float radius, Direction dir) | 添加圓形,x:圓形圓心的x坐標(biāo),y:圓形圓心的y坐標(biāo),radius:圓形半徑,dir:線的閉合方向(CW順時(shí)針方向 | CCW逆時(shí)針方向) |
| addOval(RectF oval, Direction dir) | 添加橢圓,oval:橢圓內(nèi)切的矩形區(qū)域,dir:線的閉合方向(CW順時(shí)針方向 | CCW逆時(shí)針方向) |
| addOval(float left, float top, float right, float bottom, Direction dir) | 添加橢圓,left、top、right、bottom組成橢圓內(nèi)切的矩形區(qū)域,dir:線的閉合方向(CW順時(shí)針方向 | CCW逆時(shí)針方向) |
| addRect(RectF rect, Direction dir) | 添加矩形,rect:矩形區(qū)域,dir:線的閉合方向(CW順時(shí)針方向 | CCW逆時(shí)針方向) |
| addRect(float left, float top, float right, float bottom, Direction dir) | 添加矩形,left、top、right、bottom組成矩形區(qū)域,dir:線的閉合方向(CW順時(shí)針方向 | CCW逆時(shí)針方向) |
| addRoundRect(RectF rect, float rx, float ry, Direction dir) | 添加統(tǒng)一圓角的圓角矩形,rect:矩形區(qū)域,rx:橢圓圓角的橫軸半徑,ry:橢圓圓角的縱軸半徑,dir:線的閉合方向(CW順時(shí)針方向 | CCW逆時(shí)針方向) |
| addRoundRect(float left, float top, float right, float bottom, float rx, float ry,Direction dir) | 添加統(tǒng)一圓角的圓角矩形,left、top、right、bottom組成矩形區(qū)域,rx:橢圓圓角的橫軸半徑,ry:橢圓圓角的縱軸半徑,dir:線的閉合方向(CW順時(shí)針方向 | CCW逆時(shí)針方向) |
| addRoundRect(RectF rect, float[] radii, Direction dir) | 添加非統(tǒng)一圓角的圓角矩形,rect:矩形區(qū)域,radii:矩形四個(gè)橢圓圓角的橫軸半徑和縱軸半徑的數(shù)組,一共8個(gè)數(shù)值,dir:線的閉合方向(CW順時(shí)針方向 | CCW逆時(shí)針方向) |
| addRoundRect(float left, float top, float right, float bottom, float[] radii,Direction dir) | 添加非統(tǒng)一圓角的圓角矩形,left、top、right、bottom組成矩形區(qū)域,radii:矩形四個(gè)橢圓圓角的橫軸半徑和縱軸半徑的數(shù)組,一共8個(gè)數(shù)值,dir:線的閉合方向(CW順時(shí)針方向 | CCW逆時(shí)針方向) |
| addPath(Path src) | 添加一組Path,src:要添加的Path |
| addPath(Path src, float dx, float dy) | 添加一組平移后的Path,src:要添加的Path,dx:平移的x坐標(biāo),dy:平移的y坐標(biāo) |
| addPath(Path src, Matrix matrix) | 添加一組經(jīng)過矩陣變換后的Path,src:要添加的Path,matrix:3x3的矩陣 |
1.addArc(RectF oval, float startAngle, float sweepAngle)
addArc兩個(gè)方法使用起來與arcTo(RectF oval, float startAngle, float sweepAngle,boolean forceMoveTo)中forceMoveTo設(shè)置為true效果一致,就不展開贅述了
2.addCircle(float x, float y, float radius, Direction dir)
以點(diǎn)(x,y)為圓心,添加一個(gè)半徑長(zhǎng)為radius的圓形,繪制起始角度為0°(x軸方向),繪制方向通過dir的值而定,dir為CW時(shí)順時(shí)針繪制,dir為CCW時(shí)逆時(shí)針繪制
方法比較簡(jiǎn)單,主要是對(duì)比CW和CCW的區(qū)別,我們用canvas.drawTextOnPath方法突顯順時(shí)針和逆時(shí)針繪制的效果,示例如下
path.addCircle(200,150,100, Path.Direction.CW);//順時(shí)針繪制
canvas.drawPath(path,pathPaint);
canvas.drawTextOnPath("繪制順序", path, 0, 0, paint);

path.addCircle(200,150,100, Path.Direction.CCW);//逆時(shí)針繪制
canvas.drawPath(path,pathPaint);
canvas.drawTextOnPath("繪制順序", path, 0, 0, paint);

3.addOval(RectF oval, Direction dir)
在oval矩形區(qū)域中,添加一個(gè)內(nèi)切的橢圓,繪制起始角度為0°(x軸方向),繪制方向通過dir的值而定,dir為CW時(shí)順時(shí)針繪制,dir為CCW時(shí)逆時(shí)針繪制
addOval(RectF oval, Direction dir)和addOval(float left, float top, float right, float bottom, Direction dir)效果是一樣的,就不分開講了
RectF rectF = new RectF(100,100,400,250);
path.addOval(rectF, Path.Direction.CW);
canvas.drawPath(path,pathPaint);
效果如圖

4.addRect(RectF rect, Direction dir)
添加一個(gè)區(qū)域?yàn)?strong>rect的矩形,繪制起點(diǎn)為左上角,繪制方向通過dir的值而定,dir為CW時(shí)順時(shí)針繪制,dir為CCW時(shí)逆時(shí)針繪制
addRect(RectF rect, Direction dir)和addRect(float left, float top, float right, float bottom, Direction dir)效果是一樣的,就不分開講了
RectF rectF = new RectF(100,100,400,250);
path.addRect(rectF, Path.Direction.CW);
canvas.drawPath(path,pathPaint);
canvas.drawTextOnPath("繪制順序", path, 0, 0, paint);
效果如圖

5.addRoundRect(RectF rect, float rx, float ry, Direction dir)
添加一個(gè)區(qū)域?yàn)?strong>rect的圓角矩形,四個(gè)角的圓角大小一致,圓角的橫軸半徑為rx,縱軸半徑為ry,dir為CW時(shí)順時(shí)針繪制,繪制起點(diǎn)為左下角,dir為CCW時(shí)逆時(shí)針繪制,繪制起點(diǎn)為左上角(注意對(duì)比順時(shí)針和逆時(shí)針的繪制起點(diǎn))
addRoundRect(RectF rect, float rx, float ry, Direction dir)和addRoundRect(float left, float top, float right, float bottom, float rx, float ry,Direction dir)效果是一樣的,就不分開講了
RectF rectF = new RectF(100,100,400,350);
path.addRoundRect(rectF,60,30,Path.Direction.CW);//順時(shí)針
canvas.drawPath(path,pathPaint);
canvas.drawTextOnPath("繪制順序", path, 0, 0, paint);

RectF rectF = new RectF(100,100,400,350);
path.addRoundRect(rectF,60,30,Path.Direction.CCW);//逆時(shí)針
canvas.drawPath(path,pathPaint);
canvas.drawTextOnPath("繪制順序", path, 0, 0, paint);

addRoundRect(RectF rect, float[] radii, Direction dir)
添加一個(gè)區(qū)域?yàn)?strong>rect的圓角矩形,四個(gè)角的圓角的橫軸和縱軸半徑由radii數(shù)組中的8個(gè)數(shù)值決定,dir為CW時(shí)順時(shí)針繪制,繪制起點(diǎn)為左下角,dir為CCW時(shí)逆時(shí)針繪制,繪制起點(diǎn)為左上角(注意對(duì)比順時(shí)針和逆時(shí)針的繪制起點(diǎn))
需要注意的是,如果radii數(shù)組中的元素小于8,系統(tǒng)會(huì)拋出錯(cuò)誤信息radii[] needs 8 values,如下圖所示


addRoundRect(RectF rect, float[] radii, Direction dir)和addRoundRect(float left, float top, float right, float bottom, float[] radii,Direction dir)效果是一樣的,就不分開講了
RectF rectF = new RectF(100,100,400,350);
float[] radii = {60,30,30,70,100,100,10,40};
path.addRoundRect(rectF,radii,Path.Direction.CW);
canvas.drawPath(path,pathPaint);
canvas.drawTextOnPath("繪制順序", path, 0, 0, paint);

6.addPath(Path src)
添加一組名為src的Path副本
Path copyPath = new Path();
copyPath.moveTo(100,100);
copyPath.lineTo(150,200);
copyPath.quadTo(200,100,350,200);
copyPath.lineTo(100,250);
copyPath.close();
path.addPath(copyPath);
canvas.drawPath(path,pathPaint);

addPath(Path src, float dx, float dy)
添加一組名為src的Path副本,然后將其進(jìn)行平移,x軸上的平移距離為dx,y軸上的平移距離為dy
Path copyPath = new Path();
copyPath.moveTo(100,100);
copyPath.lineTo(150,200);
copyPath.quadTo(200,100,350,200);
copyPath.lineTo(100,250);
copyPath.close();
path.addPath(copyPath,300,0);//向x軸正方向平移300像素距離
canvas.drawPath(path,pathPaint);

addPath(Path src, Matrix matrix)
添加一組名為src的Path副本,然后將其進(jìn)行矩陣變換,矩陣為matrix(3x3的矩陣)
Path copyPath = new Path();
copyPath.moveTo(100,100);
copyPath.lineTo(150,200);
copyPath.quadTo(200,100,350,200);
copyPath.lineTo(100,250);
copyPath.close();
Matrix mMatrix = new Matrix();
mMatrix.setScale(1,-1);//以x軸為中線進(jìn)行翻轉(zhuǎn)
mMatrix.postRotate(90);//以坐標(biāo)軸原點(diǎn)為中心點(diǎn)順時(shí)針旋轉(zhuǎn)90°
path.addPath(copyPath,mMatrix);
canvas.drawPath(path,pathPaint);

四、填充模式
| 方法名 | 參數(shù)解析 |
|---|---|
| setFillType(FillType ft) | 設(shè)置Path的填充模式,ft:填充類型,有EVEN_ODD ,INVERSE_EVEN_ODD ,WINDING ,INVERSE_WINDING 四種模式 |
| getFillType() | 獲取當(dāng)前Path的填充模式 |
| isInverseFillType() | 判斷當(dāng)前Path填充模式是否是反向規(guī)則(INVERSE_XXX) |
| toggleInverseFillType() | 當(dāng)前Path的填充模式與其反向規(guī)則模式進(jìn)行相互切換 |
填充模式要解釋起來還是挺費(fèi)口舌的,這里就把前輩們的博客貼出來,他們解釋得都非常清楚,我就不多贅述了
安卓自定義 View 進(jìn)階:Path 完結(jié)篇(偽)
[轉(zhuǎn)]Android Path里FillType功能
五、其他方法
| 方法名 | 參數(shù)解析 |
|---|---|
| close() | 封閉當(dāng)前Path,連接起點(diǎn)和終點(diǎn) |
| reset() | 清空Path中的所有直線和曲線,保留填充模式設(shè)置,不保留Path上相關(guān)的數(shù)據(jù)結(jié)構(gòu) |
| rewind() | 清空Path中的所有直線和曲線,不保留填充模式設(shè)置,但會(huì)保留Path上相關(guān)的數(shù)據(jù)結(jié)構(gòu),以便高效地復(fù)用 |
| set(Path src) | 用名為src的Path替換當(dāng)前的Path |
| op(Path path, Op op) | 當(dāng)前Path與名為path的Path進(jìn)行布爾運(yùn)算(取差集、交集、并集等),op:運(yùn)算邏輯,有DIFFERENCE(差集),REVERSE_DIFFERENCE(差集),INTERSECT(交集),UNION(并集),XOR(異或)五種運(yùn)算邏輯可選。ps:此方法在API 19以上有效 |
| offset(float dx, float dy) | 平移當(dāng)前Path,x軸上平移的距離為dx,y軸上平移的距離為dy |
| offset(float dx, float dy, Path dst) | 平移名為dst的Path,x軸上平移的距離為dx,y軸上平移的距離為dy |
| transform(Matrix matrix) | 對(duì)當(dāng)前Path進(jìn)行矩陣變換,矩陣為matrix(3x3矩陣) |
| transform(Matrix matrix, Path dst) | 對(duì)名為dst的Path進(jìn)行矩陣變換,矩陣為matrix(3x3矩陣) |
| setLastPoint(float dx, float dy) | 設(shè)置終點(diǎn),設(shè)置當(dāng)前Path最后一個(gè)點(diǎn)的位置為(dx,dy) |
| isEmpty() | 判斷當(dāng)前Path是否為空 |
| isConvex() | 判斷當(dāng)前Path圍成的圖形是否凸多邊形。ps:此方法在API 21以上有效 |
| isRect(RectF rect) | 判斷當(dāng)前Path是否為矩形,如是,則將當(dāng)前Path存儲(chǔ)到新建的rect中 |
這里大多數(shù)方法都比較簡(jiǎn)單,有些之前已經(jīng)應(yīng)用過,就不展開來講了,下面介紹一下其中比較特別且常用的幾個(gè)方法
1.op(Path path, Op op) 布爾運(yùn)算
前面的表格我們提到參數(shù)op共有五種運(yùn)算邏輯可選,下面我們就來看看這五種運(yùn)算邏輯是如何影響兩個(gè)Path之間的關(guān)系的,我們先用不同的顏色繪制出一個(gè)矩形和一個(gè)圓形,觀察一下它們的位置和關(guān)系
Path path1 = new Path();
path1.addRect(100,100,300,300, Path.Direction.CW);
pathPaint.setColor(Color.GREEN);
canvas.drawPath(path1,pathPaint);
Path path2 = new Path();
path2.addCircle(300,250,100,Path.Direction.CW);
pathPaint.setColor(Color.RED);
canvas.drawPath(path2,pathPaint);

下面我們對(duì)這兩個(gè)Path進(jìn)行布爾運(yùn)算
DIFFERENCE(差集)
若op方法的調(diào)用關(guān)系為path1.op(path2, Path.Op.DIFFERENCE),則運(yùn)算結(jié)果是path1減去與path2的交集后剩下的部分,即path1與path2的并集減去path2部分
Path path1 = new Path();
path1.addRect(100,100,300,300, Path.Direction.CW);
Path path2 = new Path();
path2.addCircle(300,250,100,Path.Direction.CW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path1.op(path2, Path.Op.DIFFERENCE);//path1與path2進(jìn)行布爾運(yùn)算,結(jié)果保存至path1
canvas.drawPath(path1,pathPaint);
}
//也可以這樣寫
Path path3 = new Path();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path3.op(path1,path2,Path.Op.DIFFERENCE);//path1與path2進(jìn)行布爾運(yùn)算,結(jié)果保存至path3
canvas.drawPath(path3,pathPaint);
}
可以用path1.op直接運(yùn)算,也可以新建一個(gè)path3保存path1和path2的運(yùn)算結(jié)果,效果都是一樣的

REVERSE_DIFFERENCE(差集)
若op方法的調(diào)用關(guān)系為path1.op(path2, Path.Op.REVERSE_DIFFERENCE),則運(yùn)算結(jié)果是path2減去與path1的交集后剩下的部分,即path1與path2的并集減去path1部分
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path1.op(path2, Path.Op.REVERSE_DIFFERENCE);//path1與path2進(jìn)行布爾運(yùn)算,結(jié)果保存至path1
canvas.drawPath(path1,pathPaint);
}
//也可以這樣寫
Path path3 = new Path();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path3.op(path1,path2,Path.Op.REVERSE_DIFFERENCE);//path1與path2進(jìn)行布爾運(yùn)算,結(jié)果保存至path3
canvas.drawPath(path3,pathPaint);
}

INTERSECT(交集)
若op方法的調(diào)用關(guān)系為path1.op(path2, Path.Op.INTERSECT),則運(yùn)算結(jié)果是path1與path2的交集
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path1.op(path2, Path.Op.INTERSECT);//path1與path2進(jìn)行布爾運(yùn)算,結(jié)果保存至path1
canvas.drawPath(path1,pathPaint);
}
//也可以這樣寫
Path path3 = new Path();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path3.op(path1,path2,Path.Op.INTERSECT);//path1與path2進(jìn)行布爾運(yùn)算,結(jié)果保存至path3
canvas.drawPath(path3,pathPaint);
}

UNION(并集)
若op方法的調(diào)用關(guān)系為path1.op(path2, Path.Op.UNION),則運(yùn)算結(jié)果是path1與path2的并集
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path1.op(path2, Path.Op.UNION);//path1與path2進(jìn)行布爾運(yùn)算,結(jié)果保存至path1
canvas.drawPath(path1,pathPaint);
}
//也可以這樣寫
Path path3 = new Path();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path3.op(path1,path2,Path.Op.UNION);//path1與path2進(jìn)行布爾運(yùn)算,結(jié)果保存至path3
canvas.drawPath(path3,pathPaint);
}

XOR(異或)
若op方法的調(diào)用關(guān)系為path1.op(path2, Path.Op.XOR),則運(yùn)算結(jié)果是path1與path2的并集減去path1與path2的交集
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path1.op(path2, Path.Op.XOR);//path1與path2進(jìn)行布爾運(yùn)算,結(jié)果保存至path1
canvas.drawPath(path1,pathPaint);
}
//也可以這樣寫
Path path3 = new Path();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
path3.op(path1,path2,Path.Op.XOR);//path1與path2進(jìn)行布爾運(yùn)算,結(jié)果保存至path3
canvas.drawPath(path3,pathPaint);
}

2.setLastPoint(float dx, float dy)
當(dāng)Path在調(diào)用setLastPoint方法之前執(zhí)行了某項(xiàng)操作時(shí)(繪制直線或曲線等),會(huì)將該操作的終點(diǎn)強(qiáng)制設(shè)置為(dx,dy)并連線(線的曲直取決于該操作本身是繪制直線還是曲線)
理解這個(gè)方法之前,首先我們要知道無論是使用addXxx方法還是xxxTo方法等在繪制過程中其實(shí)都是根據(jù)一堆點(diǎn)的集合,按順序連線(直線或曲線)后繪制出Path最終的樣子,setLastPoint方法正是改變此方法調(diào)用之前點(diǎn)的集合中最后一個(gè)點(diǎn)的位置。下面我們通過封閉圖形(矩形)和非封閉圖形(一段圓弧)的例子更好地理解這個(gè)方法
//用綠線繪制一個(gè)矩形
path.addRect(new RectF(100,100,300,300), Path.Direction.CW);
pathPaint.setColor(Color.GREEN);
canvas.drawPath(path,pathPaint);
//強(qiáng)制設(shè)置最后一個(gè)點(diǎn)為(150,250),用紅線繪制觀察變化
path.reset();
path.addRect(new RectF(100,100,300,300), Path.Direction.CW);
path.setLastPoint(150,250);
pathPaint.setColor(Color.RED);
canvas.drawPath(path,pathPaint);

//用綠線繪制一個(gè)旋轉(zhuǎn)180°的圓弧
path.addArc(new RectF(100,100,300,300),0,180);
pathPaint.setColor(Color.GREEN);
canvas.drawPath(path,pathPaint);
//強(qiáng)制設(shè)置最后一個(gè)點(diǎn)為(200,200),用紅線繪制觀察變化
path.reset();
path.addArc(new RectF(100,100,300,300),0,180);
path.setLastPoint(200,200);
pathPaint.setColor(Color.RED);
canvas.drawPath(path,pathPaint);

至此本篇總結(jié)到此結(jié)束,若有什么遺漏和錯(cuò)誤的地方歡迎留言指出,如果大家看了感覺還不錯(cuò)麻煩點(diǎn)個(gè)贊,你們的支持是我最大的動(dòng)力~
看完覺得手癢還可以去瞧瞧下面的教程博客練手哦?乛乛?
Android自定義View——從零開始實(shí)現(xiàn)圓形進(jìn)度條
Android自定義View——從零開始實(shí)現(xiàn)水波浪進(jìn)度框
Android自定義View——從零開始實(shí)現(xiàn)書籍翻頁(yè)效果(一)
Android自定義View——從零開始實(shí)現(xiàn)書籍翻頁(yè)效果(二)
Android自定義View——從零開始實(shí)現(xiàn)書籍翻頁(yè)效果(三)
Android自定義View——從零開始實(shí)現(xiàn)書籍翻頁(yè)效果(四)
Android自定義View——從零開始實(shí)現(xiàn)書籍翻頁(yè)效果(性能優(yōu)化篇)
Android自定義View——從零開始實(shí)現(xiàn)可展開收起的水平菜單欄