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

前面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的相關方法
作用 相關方法 備注
移動起點 [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.
連接直線 [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.
添加內容 [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)) 添加( 圓弧、 圓, 橢圓,路徑,矩形, 圓角矩形, ) 到當前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的方法是基于原點的坐標系(偏移量), rXxx方法是基于當前點坐標系(偏移量)
貝塞爾曲線 [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() 設置、切換、判斷和獲取填充模式
計算邊界 [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)
在上次的結束點和指定的點之間添加一條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
Image.png

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

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

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

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

addXXX和arcTo

這次方法主要是在Path中添加基本圖形,重點區分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進行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

方法名 作用 區別
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);
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狀態 效果
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);

Paste_Image.png

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容

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