一、通過drawPath()繪制自定義圖形
Path可以描述直線、二次曲線、三次曲線、圓、橢圓、弧形、矩形、圓角矩形。Path有兩類方法,一類是直接描述路徑的,另一類是輔助的設置或計算。
二、Path方法第一類:直接描述路徑
這類方法可以細分為兩組:添加子圖形和畫線(直線或曲線)
1、addXXX():添加子圖形
addCircle(float x, float y, float radius, Direction dir) 添加圓
/**
*
* @param x
* @param y
* @param radius
* @param dir 畫圓的路徑的方向
*/
addCircle(float x, float y, float radius, Direction dir) 添加圓
注:路徑方向有兩種:順時針 (CW clockwise) 和逆時針 (CCW counter-clockwise)。 對于普通情況,這個參數填 CW 還是填 CCW 沒有影響。它只是在需要填充圖形 (Paint.Style 為 FILL 或 FILL_AND_STROKE) ,并且圖形出現自相交時,用于判斷填充范圍的。
例子:添加一個圓
path.addCircle(300, 300, 200, Path.Direction.CW);
......
canvas.drawPath(path, paint);
Path.add-()其他方法
- addOval(float left, float top, float right, float bottom, Direction dir) / addOval(RectF oval, Direction dir)添加橢圓
- addRect(float left, float top, float right, float bottom, Direction dir) / addRect(RectF rect, Direction dir) 添加矩形
- addRoundRect(RectF rect, float rx, float ry, Direction dir) / addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Direction dir) / addRoundRect(RectF rect, float[] radii, Direction dir) / addRoundRect(float left, float top, float right, float bottom, float[] radii, Direction dir) 添加圓角矩形
- addPath(Path path) 添加另一個 Path
2、xxxTo() ——畫線(直線或曲線)
(1)lineTo(float x, float y) / rLineTo(float x, float y) 畫直線
/**
*
* @param x 目標位置X
* @param y 目標位置y
*/
lineTo(float x, float y)
從當前位置向目標位置畫一條直線, x 和 y 是目標位置的坐標。這兩個方法的區別是,lineTo(x, y) 的參數是絕對坐標,而 rLineTo(x, y) 的參數是相對當前位置的相對坐標 (前綴 r 指的就是 relatively 「相對地」)。
當前位置:所謂當前位置,即最后一次調用畫 Path 的方法的終點位置。初始值為原點 (0, 0)。
paint.setStyle(Paint.Style.STROKE);
path.lineTo(100, 100); // 由當前位置 (0, 0) 向 (100, 100) 畫一條直線
path.rLineTo(100, 0); // 由當前位置 (100, 100) 向正右方 100 像素的位置畫一條直線
canvas.drawPath(path, paint);
(2)quadTo(float x1, float y1, float x2, float y2) / rQuadTo(float dx1, float dy1, float dx2, float dy2) 畫二次貝塞爾曲線
參數:這條二次貝塞爾曲線的起點就是當前位置,而參數中的 x1, y1 和 x2, y2 則分別是控制點和終點的坐標。和 rLineTo(x, y) 同理,rQuadTo(dx1, dy1, dx2, dy2) 的參數也是相對坐標
(3)cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) / rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3) 畫三次貝塞爾曲線
(4)moveTo(float x, float y) / rMoveTo(float x, float y) 移動到目標位置
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
path.lineTo(100, 100); // 畫斜線
path.moveTo(200, 200); // 我移~~
path.lineTo(200, 0); // 畫豎線
canvas.drawPath(path, paint);
(5)arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo) / arcTo(RectF oval, float startAngle, float sweepAngle) 畫弧形
參數 forceMoveTo :繪制是要「抬一下筆移動過去」,還是「直接拖著筆過去」,區別在于是否留下移動的痕跡。
addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle) / addArc(RectF oval, float startAngle, float sweepAngle)
(6)close() 封閉當前子圖形
作用是把當前的子圖形封閉,即由當前位置向當前子圖形的起點繪制一條直線。
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(150, 150);
path.close();
canvas.drawPath(path, paint);
當需要填充,不需要close() 。Paint.Style 為 FILL 或 FILL_AND_STROKE,Path 會自動封閉子圖形。
paint.setStyle(Paint.Style.FILL);
paint.setStrokeWidth(10);
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(150, 150);
canvas.drawPath(path, paint);
三、Path方法第二類:輔助的設置或計算
1.Path.setFillType(Path.FillType ft) 設置填充方式
在二.1畫圓中,參數 Direction dir提到, Path.setFillType(fillType) 是用來設置圖形自相交時的填充算法的,不同的FillType值,有不同的填充效果。FillType的四種取值:
- EVEN_ODD
- WINDING (默認值)
- INVERSE_EVEN_ODD
- INVERSE_WINDING
(1)EVEN_ODD
即 even-odd rule (奇偶原則):對于平面中的任意一點,向任意方向射出一條射線,這條射線和圖形相交的次數(相交才算,相切不算哦)如果是奇數,則這個點被認為在圖形內部,是要被涂色的區域;如果是偶數,則這個點被認為在圖形外部,是不被涂色的區域。射線每穿過圖形中的一條線,內外狀態就發生一次切換,這就是為什么 EVEN_ODD 是一個「交叉填充」的模式。
(2)WINDING
non-zero winding rule (非零環繞數原則),首先,它需要你圖形中的所有線條都是有繪制方向的:以 0 為初始值,順時針+1,逆時針-1。結果不為0,則在圖形內部,涂色;結果為0,則在圖形外部,不被涂色。
(3)INVERSE_EVEN_ODD和 INVERSE_WINDING
與前兩個相反