繪畫是自定義View的基礎,Paint和canvas相當於繪畫中的畫筆和紙,掌握Paint和canvas可以使我們更加容易進行自定義View。
Paint:
一、setAntiAlias()
一般用於繪製不規則圖形的時候,使用抗鋸齒,比如圓形、文字等。對於規則的圖形,是不需要開啟抗鋸齒功能的,比如矩形。
二、setStyle()
設定填充的樣式,主要用於控制幾何圖形
- Paint.Style.FILL 填充內部
- Paint.Style.FILL_AND_STROKE 填充內部和描邊
- Paint.Style.STROKE 僅描邊
三、setStrokeWidth()
設定畫筆的寬度,單位是px.對畫筆的STYLE設定成STROKE和FILL_AND_STROKE時有效。但畫支線時無論style設定什麼值,均有效。
注意事項:
當設定較大stroke畫圓,並且繪畫的範圍佔滿(基本佔滿)畫布或rect時,stroke會超出繪畫範圍。此時需要將原來的圓半徑減去stroke一半得到的長度作為新圓的半徑。stroke超出的長度其實為stroke寬度的一半。
對於橢圓也差不多:
四、Paint.Cap
Cap指定了描邊線和路徑的開始和結束的處理。預設為BUTT。
- Paint.Cap.BUTT 無線帽
- Paint.Cap.ROUND 圓形線帽
- Paint.Cap.SQUARE 方形線帽
五、Paint.Join
Join指定線條和曲線段在描邊路徑上連線的處理。預設為MITER。
- Paint.Join.BEVEL 連線的外邊緣以直線相交
- Paint.Join.MITER 連線的外邊緣以銳角相交
- Paint.Join.ROUND 連線的外邊緣以圓弧相交
當畫筆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型別。
畫圓角矩形:
- rect 矩形的範圍
- rx 生成圓角的x軸半徑
- ry 生成圓角的y軸半徑
但drawRoundRect()方法只能生成四個圓角都是一致的矩形:
如果想生成圓角不一致的圓角,可使用shape標籤:
四、畫弧
- RectF 圓弧繪畫的矩形範圍。
- startAngle 開始的角度。
- sweepAngle 整條弧跨越的弧度。
- useCenter 如果為true,則在弧形中包含橢圓的中心並閉合它。
畫筆不同的style和drawArc()useCenter的值可繪畫出不同的圓弧或弧線:
注意事項:
canvas畫弧時,0度的起始位置在x軸正方向上。
五、畫文字
- text 繪畫的文字
- start 第一個字元的索引
- end 文字的最後一個字元的索引
- x 文字繪畫的起始x軸位置
- y 基線(BaseLine)
前面幾個引數都很好理解,無非就是文字、索引值和繪畫起始的x軸位置,但基線是什麼,怎麼求呢?
Baseline是文字繪製時所參照的基準線,觀察下圖可看見基線是大部分英文字母的底部沿線。只有確定Baseline的位置,才能將文字準確的繪製在我們想要的位置上。
需要先理清楚一些概念:
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
中心線是按文字的所在的位置決定的。以聯絡人中的字母索引列表為例,每個字母的所需要繪畫的高都不一樣,需要計算每個字母可佔據的高度,再除以一半求出中心線的位置。
六、裁剪
剪下是對canvas的裁剪操作,並不影響原來的之前已經畫好的圖形。
以clipRect()裁剪變色字型為例:
七、save()和restore()
每次呼叫save(),都會先儲存當前畫布的狀態,然後將其放入到特定的棧中。
每次呼叫restore(),都會把棧頂的畫布取出來,並按照這個狀態恢復當前的畫布,然後在這個畫布上作畫。
clipXX系列的函式對畫布的操作是不可逆的,除非呼叫了save()和restore()對畫布進行儲存和恢復。
Path:
path代表路徑,在canvas中使用drawPath(Path,Paint)進行繪畫路徑。
一、畫直線路徑
void moveTo(float x1,float y1)
void lineTo(float x2,float y2)
void close()
複製程式碼
(x1,y1)是直線的起始點,(x2,y2)是直線的終點,又是下一個繪製直線路徑的起始點,lineTo可以無限用。
呼叫了moveTo()後,呼叫lineTo()畫了N條直線,還沒有形成閉環的話,可以呼叫close()將路徑的首尾連線起來。
二、畫弧形路徑
使用3參的arcTo()方法畫出的弧會和起始點相連,因為預設情況下路徑都是連貫的,除非以下兩種情況:
1、呼叫addXX系列函式,直接新增固定形狀的路徑
2、moveTo()改變起始位置
呼叫4參的arcTo()方法,將第4個引數forceMoveTo設定為true,會使弧的起始點作為繪製的起始點。
三、addXXX系列函式
路徑預設是連貫的,但addXXX()系列函式可以直接新增一些固定形狀的路徑,不必考慮連貫性。
1、新增矩形路徑
Path.Direction 用於指定如何封閉的形狀(如矩形、橢圓形)。
- Path.Direction.CCW: 指建立逆時針方向的矩形路徑。
- Path.Direction.CW: 指建立順時針方向的矩形路徑。
目前順時針和逆時針的生成對矩形圖形並無影響,但對於根據路徑方向繪畫文字等,則會起到關鍵作用。
2、新增圓角矩形路徑
繪畫圓角矩形路徑對比繪畫圓角矩形多了兩個過載方法,其中float[] radii引數時用於定義4個角的橢圓各自的x軸半徑和y軸半徑,換句話說,即使用addRoundRect()也可以實現4個圓角不同的矩形。但圓角的順序並不因為Path.Direction值的不同而有所改變。
3、新增圓形路徑
具體引數和canvas繪製圓一樣, x 為圓心X軸座標, y 為圓心y軸座標,radius 為圓的半徑。
4、新增橢圓路徑
具體引數和canvas繪製橢圓一樣
5、新增圓弧路徑
具體引數和canvas繪製圓弧一樣
補充:
一、測量文字寬高
1、通過Paint.measureText測量文字寬度
2、通過Paint.getTextBounds獲得文字所在的矩形區域,可以的到寬高
3、通過Paint.FontMetrics or Paint.FontMetricsInt獲得文字寬度
一般使用方案二進行對文字寬高的測量,最精準。
demo連結:
連結:pan.baidu.com/s/1GrP1XYFg…
提取碼:wubw