Android自定義控件(三 .0)Path的基本操作

前面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)方法
作用 相關(guān)方法 備注
移動起點 [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).
設(shè)置終點 [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.
連接直線 [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).
閉合路徑 close() Close the current contour.
添加內(nèi)容 [addArc](https://developer.android.google.cn/reference/android/graphics/Path.html#addArc(float, float, float, float, float, float))、[addCircle](https://developer.android.google.cn/reference/android/graphics/Path.html#addCircle(float, float, float, android.graphics.Path.Direction))、[addOval](https://developer.android.google.cn/reference/android/graphics/Path.html#addOval(android.graphics.RectF, android.graphics.Path.Direction))、[addPath](https://developer.android.google.cn/reference/android/graphics/Path.html#addPath(android.graphics.Path, android.graphics.Matrix))、[addRect](https://developer.android.google.cn/reference/android/graphics/Path.html#addRect(android.graphics.RectF, android.graphics.Path.Direction))、[addRoundRect](https://developer.android.google.cn/reference/android/graphics/Path.html#addRoundRect(android.graphics.RectF, float, float, android.graphics.Path.Direction))、[arcTo](https://developer.android.google.cn/reference/android/graphics/Path.html#arcTo(android.graphics.RectF, float, float, boolean)) 添加( 圓弧、 圓, 橢圓,路徑,矩形, 圓角矩形, ) 到當(dāng)前Path
是否為空 isEmpty() Returns true if the path is empty (contains no lines or curves)
是否為矩形 isRect(RectF rect) Returns true if the path specifies a rectangle.
替換路徑 set(Path src) Replace the contents of this with the contents of src.
偏移路徑 [offset](https://developer.android.google.cn/reference/android/graphics/Path.html#offset(float, float)) Offset the path by (dx,dy)
重置路徑 reset()、rewind() Clear any lines and curves from the path, making it empty./Rewinds the path: clears any lines and curves from the path but keeps the internal data structure for faster reuse.
rXxx方法 [rCubicTo](https://developer.android.google.cn/reference/android/graphics/Path.html#rCubicTo(float, float, float, float, float, float))、[rLineTo](https://developer.android.google.cn/reference/android/graphics/Path.html#rLineTo(float, float))、[rMoveTo](https://developer.android.google.cn/reference/android/graphics/Path.html#rMoveTo(float, float))、[rQuadTo](https://developer.android.google.cn/reference/android/graphics/Path.html#rQuadTo(float, float, float, float)) 不帶r的方法是基于原點的坐標(biāo)系(偏移量), rXxx方法是基于當(dāng)前點坐標(biāo)系(偏移量)
貝塞爾曲線 [quadTo](https://developer.android.google.cn/reference/android/graphics/Path.html#quadTo(float, float, float, float))、[cubicT](https://developer.android.google.cn/reference/android/graphics/Path.html#cubicTo(float, float, float, float, float, float)) 分別為二次和三次貝塞爾曲線的方法
矩陣操作 transform Transform the points in this path by matrix
填充模式 setFillType、toggleInverseFillType()、isInverseFillType()、getFillType() 設(shè)置、切換、判斷和獲取填充模式
計算邊界 [computeBounds](https://developer.android.google.cn/reference/android/graphics/Path.html#computeBounds(android.graphics.RectF, boolean)) Compute the bounds of the control points of the path, and write the answer into bounds.
布爾操作 [op](https://developer.android.google.cn/reference/android/graphics/Path.html#op(android.graphics.Path, android.graphics.Path, android.graphics.Path.Op)) Set this path to the result of applying the Op to the two specified paths
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
Image.png

在例子中,我們調(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);
Image.png

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) 之間的連線。

Image.png
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);
Image.png

注意:close的作用是封閉路徑,與連接當(dāng)前最后一個點和第一個點并不等價。如果連接了最后一個點和第一個點仍然無法形成封閉圖形,則close什么 也不做。

addXXX和arcTo

這次方法主要是在Path中添加基本圖形,重點區(qū)分addArc與arcTo。

類型 解釋 說明
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);
Image.png
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);
Paste_Image.png

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);
Paste_Image.png
isEmpty、 isRect、isConvex、 set 和 offset
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);

Paste_Image.png

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 最近項目中要實現(xiàn)加速球效果。是時候該學(xué)習(xí)一波了,好了廢話不多說,記筆記,還是從自己發(fā)憷的自定義view開始。 先來...
    laifrog閱讀 1,740評論 0 4
  • 版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。系列教程:Android開發(fā)之從零開始系列大家要是看到有錯誤的...
    Anlia閱讀 21,192評論 1 24
  • 什么是Path? 我們先看看Android官方文檔給出的定義: The Path class encapsulat...
    一團(tuán)撈面閱讀 7,026評論 13 127
  • 系列文章之 Android中自定義View(一)系列文章之 Android中自定義View(二)系列文章之 And...
    YoungerDev閱讀 4,627評論 3 11
  • 我想,六歲以前的事我大概什么都不記得了吧。還沒有上學(xué)的時候,應(yīng)該一切都是無憂無慮的樣子。 不過清楚地記得一個場景,...
    用你的感覺閱讀 124評論 0 0

友情鏈接更多精彩內(nèi)容