Android自定義View 1-1 接上:畫自定義圖形

學習http://hencoder.com/ui-1-1/筆記

一、通過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);
1.png
2.png

當需要填充,不需要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
與前兩個相反

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 系列文章之 Android中自定義View(一)系列文章之 Android中自定義View(二)系列文章之 And...
    YoungerDev閱讀 4,474評論 3 11
  • 作者:扔物線 鏈接:https://juejin.im/post/5962a3746fb9a06ba2687226...
    不怕曬閱讀 487評論 0 0
  • 自定義繪制概述 方法:重寫繪制方法(最常用:onDraw()) 繪制的關鍵:CanvasCanvas的繪制類方法:...
    NewSalton閱讀 467評論 0 0
  • 最近開始早上讀詩經,想著沾點詩意,讓生活也如詩般瑯瑯上口,不瑣碎啰嗦 兒子看我早上念詩經,有時會一臉傻傻地看著我,...
    泡泡侯閱讀 1,098評論 1 2
  • 我以前5、6歲的時候,最愛玩的是遙控的機車,遙控飛機和遙控機器人,那是我以前最喜歡的。 我為什么我喜歡...
    黃浚鎧閱讀 617評論 5 2