前面http://www.itdecent.cn/p/35765aa6f7d9 所講的繪制的圖形都是基本的簡單圖形,如矩形,員,圓弧等。如果對于一些復(fù)雜的圖形(五角星,心形)的繪制,前面的繪圖方法就無能為力了。而使用Path不僅可以繪制簡單的圖形,還能復(fù)制一些復(fù)雜的圖形。
Google官網(wǎng)上Path的鏈接為:https://developer.android.google.cn/reference/android/graphics/Path.html
google官網(wǎng)上對path的解釋為:
- The Path class encapsulates compound (multiple contour) geometric paths consisting of straight line segments, quadratic curves, and cubic curves. It can be drawn with canvas.drawPath(path, paint), either filled or stroked (based on the paint's Style), or it can be used for clipping or to draw text on a path.
- 大意是Path類封裝了直線段,二次bezier曲線,三次bezier曲線等幾何路徑,可以通過canvas.drawPath(path, paint)方法畫出,畫筆的類型可以是filled 或者 stroked,可以用于通過路徑裁剪或者繪制文本。
Path的相關(guān)方法
lineTo
首先先要說的是lineTo ,lineTo的方法如下:
[lineTo](https://developer.android.google.cn/reference/android/graphics/Path.html#lineTo(float, float))(float x, float y)
Add a line from the last point to the specified point (x,y)
在上次的結(jié)束點和指定的點之間添加一條line,the last point是上次操作結(jié)束的點,如果沒有上次結(jié)束的點呢,額,那就默認(rèn)為坐標(biāo)原點。
現(xiàn)在測試一下:
int mWidth = getWidth();
int mHeight = getHeight();
canvas.translate(mWidth/2,mHeight/2); //坐標(biāo)移動到屏幕中心
Path path=new Path(); //創(chuàng)建Path
path.lineTo(200,200);
path.lineTo(200,-200);
canvas.drawPath(path,mPaint2); //繪制Path

在例子中,我們調(diào)用了兩次lineTo,第一次調(diào)用時,因為之前沒有調(diào)用過,所以默認(rèn)點是坐標(biāo)原點,第二次調(diào)用時,因為上次調(diào)用的結(jié)束點是(200,200),所以這次lineTo是(200,200)到(200,-200)之間的連線。
moveTo 和 setLastPoint:
[moveTo](https://developer.android.google.cn/reference/android/graphics/Path.html#moveTo(float, float))(float x, float y) :Set the beginning of the next contour to the point (x,y).
[setLastPoint](https://developer.android.google.cn/reference/android/graphics/Path.html#setLastPoint(float, float))(float dx, float dy):Sets the last point of the path
這兩個方法看起來比較類似,其實是有很大不同的,如下表所示:
方法名 | 簡介 | 是否影響之前的操作 | 是否影響之后操作
------------|---------|--------------|--------------|------------
[moveTo](https://developer.android.google.cn/reference/android/graphics/Path.html#moveTo(float, float))(float x, float y)|設(shè)置下次Path的起點|否|是
[setLastPoint](https://developer.android.google.cn/reference/android/graphics/Path.html#setLastPoint(float, float))(float dx, float dy)|設(shè)置上次操作最后一個點的位置|是|是
直接上代碼:
canvas.translate(mWidth / 2, mHeight / 2);
Path path = new Path();
path.lineTo(200,200);
path.moveTo(200,0);
path.lineTo(200,-200);
canvas.drawPath(path,mPaint2);

moveTo只改變下次操作的起點,在執(zhí)行完第一次LineTo的時候,本來的默認(rèn)點位置是(200,200),但是moveTo將其改變成為了(200,0),所以在第二次調(diào)用lineTo的時候就是連接(200,0) 到 (200,-200) 之間的直線。
- 下面是setLastPoint
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
path.lineTo(200,200);
canvas.drawPoint(200,200,mPaint2);
path.setLastPoint(200,100);
path.lineTo(200,-200);
canvas.drawPath(path,mPaint2);
setLastPoint是重置上一次操作的最后一個點,在執(zhí)行完第一次的lineTo的時候,最后一個點是(200,200),而setLastPoint更改最后一個點為(200,100),所以在實際執(zhí)行的時候,第一次的lineTo就不是從原點到(200,200)的連線了,而變成了從原點到C(200,100)之間的連線了。
在執(zhí)行完第一次lineTo和setLastPoint后,最后一個點的位置是(200,100),所以在第二次調(diào)用lineTo的時候就是(200,100) 到 (200,-200) 之間的連線。

close
close():Close the current contour
close方法用于連接當(dāng)前最后一個點和最初的一個點(如果兩個點不重合的話),最終形成一個封閉的圖形。
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
path.lineTo(200,200); path.lineTo(200,-200);
path.close();
canvas.drawPath(path,mPaint2);

注意:close的作用是封閉路徑,與連接當(dāng)前最后一個點和第一個點并不等價。如果連接了最后一個點和第一個點仍然無法形成封閉圖形,則close什么 也不做。
addXXX和arcTo
這次方法主要是在Path中添加基本圖形,重點區(qū)分addArc與arcTo。
- 添加基本形狀
1.添加圓形
[addCircle](https://developer.android.google.cn/reference/android/graphics/Path.html#addCircle(float, float, float, android.graphics.Path.Direction))(float x, float y, float radius, Path.Direction dir)
2.添加橢圓
[addOval](https://developer.android.google.cn/reference/android/graphics/Path.html#addOval(android.graphics.RectF, android.graphics.Path.Direction))(RectF oval, Path.Direction dir)
[addOval](https://developer.android.google.cn/reference/android/graphics/Path.html#addOval(float, float, float, float, android.graphics.Path.Direction))(float left, float top, float right, float bottom, Path.Direction dir)
3.添加矩形
[addRect](https://developer.android.google.cn/reference/android/graphics/Path.html#addRect(android.graphics.RectF, android.graphics.Path.Direction))(RectF rect, Path.Direction dir)
[addRect](https://developer.android.google.cn/reference/android/graphics/Path.html#addRect(float, float, float, float, android.graphics.Path.Direction))(float left, float top, float right, float bottom, Path.Direction dir)
4.添加圓角矩形
[addRoundRect](https://developer.android.google.cn/reference/android/graphics/Path.html#addRoundRect(android.graphics.RectF, float, float, android.graphics.Path.Direction))(RectF rect, float rx, float ry, Path.Direction dir)
[addRoundRect](https://developer.android.google.cn/reference/android/graphics/Path.html#addRoundRect(float, float, float, float, float, float, android.graphics.Path.Direction))(float left, float top, float right, float bottom, float rx, float ry, Path.Direction dir)
可以看到,上述方法都有一個參數(shù), Path.Direction dir,具體是做什么的呢
Direction的意思是 方向,趨勢。 點進(jìn)去看一下會發(fā)現(xiàn)Direction是一個枚舉(Enum)類型,里面只有兩個枚舉常量,如下:
| 類型 | 解釋 | 說明 |
|---|---|---|
| CW | clockwise | 順時針 |
| CCW | counter-clockwise | 逆時針 |
addPath
addPath(Path src) :Add a copy of src to the path
[addPath](https://developer.android.google.cn/reference/android/graphics/Path.html#addPath(android.graphics.Path, float, float))(Path src, float dx, float dy):Add a copy of src to the path, offset by (dx,dy)
[addPath](https://developer.android.google.cn/reference/android/graphics/Path.html#addPath(android.graphics.Path, android.graphics.Matrix))(Path src, Matrix matrix):Add a copy of src to the path, transformed by matrix
addPath方法很明了,就是把兩個Path合并為一個
第二個方法是將src平移后再合并在一起
第三個方法是將src進(jìn)行Matrix變換后再合并到一起
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
Path src=new Path();
path.addRect(-200,-200,200,200,Path.Direction.CW);
src.addCircle(0,0,100,Path.Direction.CW);
path.addPath(src,0,-200);
canvas.drawPath(path,mPaint2);

addArc與arcTo
[addArc](https://developer.android.google.cn/reference/android/graphics/Path.html#addArc(android.graphics.RectF, float, float))(RectF oval, float startAngle, float sweepAngle)--- Add the specified arc to the path as a new contour.
[addArc](https://developer.android.google.cn/reference/android/graphics/Path.html#addArc(float, float, float, float, float, float))(float left, float top, float right, float bottom, float startAngle, float sweepAngle)---Add the specified arc to the path as a new contour
[arcTo](https://developer.android.google.cn/reference/android/graphics/Path.html#arcTo(android.graphics.RectF, float, float, boolean))(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)---Append the specified arc to the path as a new contour.
[arcTo](https://developer.android.google.cn/reference/android/graphics/Path.html#arcTo(float, float, float, float, float, float, boolean))(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo)--Append the specified arc to the path as a new contour.
[arcTo](https://developer.android.google.cn/reference/android/graphics/Path.html#arcTo(android.graphics.RectF, float, float, boolean))(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)---Append the specified arc to the path as a new contour
| 方法名 | 作用 | 區(qū)別 |
|---|---|---|
| addArc | 添加一個圓弧到path | 直接添加一個圓弧到path |
| arcTo | 添加一個圓弧到path | 如果圓弧的起點和上次最后一個坐標(biāo)點不同,就連接兩個點 |
另外,可以看到arcTo方法最后一個參數(shù)是個boolean類型的,forceMoveTo,有什么作用呢
| forceMoveTo | 含義 |
|---|---|
| true | 將最后一個點移動到圓弧起點,即不連接最后一個點與圓弧起點 |
| false | 不移動,而是連接最后一個點與圓弧起點 |
addArc
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
path.lineTo(100,100);
RectF oval=new RectF(0,0,300,300);
path.addArc(oval,0,270);
canvas.drawPath(path,mPaint2);

arcTo
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
path.lineTo(100,100);
RectF oval=new RectF(0,0,300,300);
path.arcTo(oval,0,270);
canvas.drawPath(path,mPaint2);

isEmpty、 isRect、isConvex、 set 和 offset
-
isEmpty()--Returns true if the path is empty (contains no lines or curves)
主要是判斷path是否為空 -
isRect(RectF rect):Returns true if the path specifies a rectangle.
判斷path是否是一個矩形 -
set(Path src):Replace the contents of this with the contents of src
將新的path賦值到就得path - [offset](https://developer.android.google.cn/reference/android/graphics/Path.html#offset(float, float))(float dx, float dy)
- [offset](https://developer.android.google.cn/reference/android/graphics/Path.html#offset(float, float, android.graphics.Path))(float dx, float dy, Path dst)
將path進(jìn)行平移
可以看到第二個方法多了一個dst參數(shù),有什么不同呢
| dst狀態(tài) | 效果 |
|---|---|
| dst不為空 | 將當(dāng)前path平移后的狀態(tài)存入dst中,不會影響當(dāng)前path |
| dst為空(null) | 平移將作用于當(dāng)前path,相當(dāng)于第一種方法 |
canvas.translate(mWidth/2,mHeight/2);
Path path=new Path();
path.addCircle(0,0,100,Path.Direction.CW);
Path dst=new Path();
path.offset(300,0,dst);
canvas.drawPath(path,mPaint2);
path.offset(300,0);
canvas.drawPath(path,mPaint2);

代碼下載地址
https://github.com/baojie0327/ViewAndGroup