前面http://www.lxweimin.com/p/35765aa6f7d9 所講的繪制的圖形都是基本的簡單圖形,如矩形,員,圓弧等。如果對于一些復雜的圖形(五角星,心形)的繪制,前面的繪圖方法就無能為力了。而使用Path不僅可以繪制簡單的圖形,還能復制一些復雜的圖形。
Google官網上Path的鏈接為:https://developer.android.google.cn/reference/android/graphics/Path.html
google官網上對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的相關方法
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)
在上次的結束點和指定的點之間添加一條line,the last point是上次操作結束的點,如果沒有上次結束的點呢,額,那就默認為坐標原點。
現在測試一下:
int mWidth = getWidth();
int mHeight = getHeight();
canvas.translate(mWidth/2,mHeight/2); //坐標移動到屏幕中心
Path path=new Path(); //創建Path
path.lineTo(200,200);
path.lineTo(200,-200);
canvas.drawPath(path,mPaint2); //繪制Path
在例子中,我們調用了兩次lineTo,第一次調用時,因為之前沒有調用過,所以默認點是坐標原點,第二次調用時,因為上次調用的結束點是(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)|設置下次Path的起點|否|是
[setLastPoint](https://developer.android.google.cn/reference/android/graphics/Path.html#setLastPoint(float, float))(float dx, float dy)|設置上次操作最后一個點的位置|是|是
直接上代碼:
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只改變下次操作的起點,在執行完第一次LineTo的時候,本來的默認點位置是(200,200),但是moveTo將其改變成為了(200,0),所以在第二次調用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是重置上一次操作的最后一個點,在執行完第一次的lineTo的時候,最后一個點是(200,200),而setLastPoint更改最后一個點為(200,100),所以在實際執行的時候,第一次的lineTo就不是從原點到(200,200)的連線了,而變成了從原點到C(200,100)之間的連線了。
在執行完第一次lineTo和setLastPoint后,最后一個點的位置是(200,100),所以在第二次調用lineTo的時候就是(200,100) 到 (200,-200) 之間的連線。
close
close():Close the current contour
close方法用于連接當前最后一個點和最初的一個點(如果兩個點不重合的話),最終形成一個封閉的圖形。
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的作用是封閉路徑,與連接當前最后一個點和第一個點并不等價。如果連接了最后一個點和第一個點仍然無法形成封閉圖形,則close什么 也不做。
addXXX和arcTo
這次方法主要是在Path中添加基本圖形,重點區分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)
可以看到,上述方法都有一個參數, Path.Direction dir,具體是做什么的呢
Direction的意思是 方向,趨勢。 點進去看一下會發現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進行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
方法名 | 作用 | 區別 |
---|---|---|
addArc | 添加一個圓弧到path | 直接添加一個圓弧到path |
arcTo | 添加一個圓弧到path | 如果圓弧的起點和上次最后一個坐標點不同,就連接兩個點 |
另外,可以看到arcTo方法最后一個參數是個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進行平移
可以看到第二個方法多了一個dst參數,有什么不同呢
dst狀態 | 效果 |
---|---|
dst不為空 | 將當前path平移后的狀態存入dst中,不會影響當前path |
dst為空(null) | 平移將作用于當前path,相當于第一種方法 |
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