Android的Paint、Canvas和Path基本使用總結

大棋發表於2019-03-04

     繪畫是自定義View的基礎,Paint和canvas相當於繪畫中的畫筆和紙,掌握Paint和canvas可以使我們更加容易進行自定義View。

Paint:

     一、setAntiAlias()
        一般用於繪製不規則圖形的時候,使用抗鋸齒,比如圓形、文字等。對於規則的圖形,是不需要開啟抗鋸齒功能的,比如矩形。

Android的Paint、Canvas和Path基本使用總結

     二、setStyle()
        設定填充的樣式,主要用於控制幾何圖形

  • Paint.Style.FILL 填充內部
  • Paint.Style.FILL_AND_STROKE 填充內部和描邊
  • Paint.Style.STROKE 僅描邊
    Android的Paint、Canvas和Path基本使用總結

     三、setStrokeWidth()
        設定畫筆的寬度,單位是px.對畫筆的STYLE設定成STROKE和FILL_AND_STROKE時有效。但畫支線時無論style設定什麼值,均有效。

Android的Paint、Canvas和Path基本使用總結

注意事項:
     當設定較大stroke畫圓,並且繪畫的範圍佔滿(基本佔滿)畫布或rect時,stroke會超出繪畫範圍。此時需要將原來的圓半徑減去stroke一半得到的長度作為新圓的半徑。stroke超出的長度其實為stroke寬度的一半。

Android的Paint、Canvas和Path基本使用總結
Android的Paint、Canvas和Path基本使用總結

對於橢圓也差不多:

Android的Paint、Canvas和Path基本使用總結
Android的Paint、Canvas和Path基本使用總結

     四、Paint.Cap
        Cap指定了描邊線和路徑的開始和結束的處理。預設為BUTT。

  • Paint.Cap.BUTT 無線帽
  • Paint.Cap.ROUND 圓形線帽
  • Paint.Cap.SQUARE 方形線帽
    Android的Paint、Canvas和Path基本使用總結

     五、Paint.Join
        Join指定線條和曲線段在描邊路徑上連線的處理。預設為MITER。

  • Paint.Join.BEVEL 連線的外邊緣以直線相交
  • Paint.Join.MITER 連線的外邊緣以銳角相交
  • Paint.Join.ROUND 連線的外邊緣以圓弧相交
Android的Paint、Canvas和Path基本使用總結

        當畫筆style設定為STROKE或者FILL_AND_STROKE時,繪畫圖形或繪畫路徑,會根據畫筆的Join值對線與線之間的結合處進行處理。

Canvas:

     一、畫背景
        canvas提供3種方法可以用於繪製畫布的背景

void drawColor(int color)
void drawARGB(int a,int r,int g,int b)
void drawRGB(int r,int g,int b)
複製程式碼

     二、畫直線

  • startX: 起始點X座標
  • startY: 起始點Y座標
  • stopX: 終點X座標
  • stopY: 終點Y座標
void drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
複製程式碼

     三、畫矩形
          矩形的範圍可以使用兩個矩形工具類進行設定:Rect 和 RectF,兩者的主要區別就是Rect儲存的上下左右均為Int型別,而RectF儲存的上下左右均為Float型別。

Android的Paint、Canvas和Path基本使用總結

     畫圓角矩形:

  • rect 矩形的範圍
  • rx 生成圓角的x軸半徑
  • ry 生成圓角的y軸半徑
    Android的Paint、Canvas和Path基本使用總結

    但drawRoundRect()方法只能生成四個圓角都是一致的矩形:

    Android的Paint、Canvas和Path基本使用總結

    如果想生成圓角不一致的圓角,可使用shape標籤:

    Android的Paint、Canvas和Path基本使用總結

     四、畫弧

  • RectF 圓弧繪畫的矩形範圍。
  • startAngle 開始的角度。
  • sweepAngle 整條弧跨越的弧度。
  • useCenter 如果為true,則在弧形中包含橢圓的中心並閉合它。
    Android的Paint、Canvas和Path基本使用總結

    畫筆不同的style和drawArc()useCenter的值可繪畫出不同的圓弧或弧線:

    Android的Paint、Canvas和Path基本使用總結

注意事項:
     canvas畫弧時,0度的起始位置在x軸正方向上。

Android的Paint、Canvas和Path基本使用總結

     五、畫文字

  • text 繪畫的文字
  • start 第一個字元的索引
  • end 文字的最後一個字元的索引
  • x 文字繪畫的起始x軸位置
  • y 基線(BaseLine)
Android的Paint、Canvas和Path基本使用總結

     前面幾個引數都很好理解,無非就是文字、索引值和繪畫起始的x軸位置,但基線是什麼,怎麼求呢?
Baseline是文字繪製時所參照的基準線,觀察下圖可看見基線是大部分英文字母的底部沿線。只有確定Baseline的位置,才能將文字準確的繪製在我們想要的位置上。

Android的Paint、Canvas和Path基本使用總結

需要先理清楚一些概念:
     1、基線並不是中心線
     2、FontMetricsInt.top表示BaseLine到頂部的距離
     3、FontMetricsInt.bottom表示BaseLine到底部的距離
     4、dy表示BaseLine到中心線的距離
     5、BaseLine = 中心線 + dy
     6、dy = 中心線 – FontMetricsInt.bottom。因為FontMetricsInt.bottom表示BaseLine到底部的距離。
     7、FontMetricsInt.top是一個負值,FontMetricsInt.bottom是一個正數。所以求改文字的中心線時,等於(FontMetricsInt.bottom – FontMetricsInt.top)/ 2

Android的Paint、Canvas和Path基本使用總結

     中心線是按文字的所在的位置決定的。以聯絡人中的字母索引列表為例,每個字母的所需要繪畫的高都不一樣,需要計算每個字母可佔據的高度,再除以一半求出中心線的位置。

Android的Paint、Canvas和Path基本使用總結

     六、裁剪
     剪下是對canvas的裁剪操作,並不影響原來的之前已經畫好的圖形。
     以clipRect()裁剪變色字型為例:

Android的Paint、Canvas和Path基本使用總結

     七、save()和restore()
     每次呼叫save(),都會先儲存當前畫布的狀態,然後將其放入到特定的棧中。
     每次呼叫restore(),都會把棧頂的畫布取出來,並按照這個狀態恢復當前的畫布,然後在這個畫布上作畫。
     clipXX系列的函式對畫布的操作是不可逆的,除非呼叫了save()和restore()對畫布進行儲存和恢復。

Path:

     path代表路徑,在canvas中使用drawPath(Path,Paint)進行繪畫路徑。

Android的Paint、Canvas和Path基本使用總結

     一、畫直線路徑

void moveTo(float x1,float y1)
void lineTo(float x2,float y2)
void close()
複製程式碼

     (x1,y1)是直線的起始點,(x2,y2)是直線的終點,又是下一個繪製直線路徑的起始點,lineTo可以無限用。
     呼叫了moveTo()後,呼叫lineTo()畫了N條直線,還沒有形成閉環的話,可以呼叫close()將路徑的首尾連線起來。

Android的Paint、Canvas和Path基本使用總結

     二、畫弧形路徑

Android的Paint、Canvas和Path基本使用總結

     使用3參的arcTo()方法畫出的弧會和起始點相連,因為預設情況下路徑都是連貫的,除非以下兩種情況:
     1、呼叫addXX系列函式,直接新增固定形狀的路徑
     2、moveTo()改變起始位置
呼叫4參的arcTo()方法,將第4個引數forceMoveTo設定為true,會使弧的起始點作為繪製的起始點。

Android的Paint、Canvas和Path基本使用總結
Android的Paint、Canvas和Path基本使用總結

     三、addXXX系列函式
     路徑預設是連貫的,但addXXX()系列函式可以直接新增一些固定形狀的路徑,不必考慮連貫性。
     1、新增矩形路徑

Android的Paint、Canvas和Path基本使用總結

Path.Direction 用於指定如何封閉的形狀(如矩形、橢圓形)。

  • Path.Direction.CCW: 指建立逆時針方向的矩形路徑。
  • Path.Direction.CW: 指建立順時針方向的矩形路徑。
Android的Paint、Canvas和Path基本使用總結

     目前順時針和逆時針的生成對矩形圖形並無影響,但對於根據路徑方向繪畫文字等,則會起到關鍵作用。

     2、新增圓角矩形路徑

Android的Paint、Canvas和Path基本使用總結

     繪畫圓角矩形路徑對比繪畫圓角矩形多了兩個過載方法,其中float[] radii引數時用於定義4個角的橢圓各自的x軸半徑和y軸半徑,換句話說,即使用addRoundRect()也可以實現4個圓角不同的矩形。但圓角的順序並不因為Path.Direction值的不同而有所改變。

Android的Paint、Canvas和Path基本使用總結

     3、新增圓形路徑

Android的Paint、Canvas和Path基本使用總結

     具體引數和canvas繪製圓一樣, x 為圓心X軸座標, y 為圓心y軸座標,radius 為圓的半徑。

     4、新增橢圓路徑

Android的Paint、Canvas和Path基本使用總結

     具體引數和canvas繪製橢圓一樣

     5、新增圓弧路徑

Android的Paint、Canvas和Path基本使用總結

     具體引數和canvas繪製圓弧一樣

補充:

     一、測量文字寬高
     1、通過Paint.measureText測量文字寬度
     2、通過Paint.getTextBounds獲得文字所在的矩形區域,可以的到寬高
     3、通過Paint.FontMetrics or Paint.FontMetricsInt獲得文字寬度

Android的Paint、Canvas和Path基本使用總結

一般使用方案二進行對文字寬高的測量,最精準。

demo連結:
連結:pan.baidu.com/s/1GrP1XYFg…
提取碼:wubw

相關文章