一、概述
經過前面對繪製原理的學習,我們知道當View
的onDraw(Canvas canvas)
方法被呼叫時,會傳入一個canvas
,我們通過這個canvas
進行繪製,即可得到對應的影像。
我們主要了解以下幾個方面:
Canvas
的含義- 如何獲得
Canvas
Canvas
的變換Canvas
的繪圖- 恢復和儲存
二、Canvas
的含義
涉及到Canvas
的主要有以下三個概念:畫板、畫布和圖層,畫板包含了多個畫布,每個畫布中間又可能會包含多個圖層,同一層級的元素會疊加在一塊,在上一層中間進行展示。
- 畫板 畫板用來承載畫布。
- 畫布
每一個畫布就是一個
bitmap
,所有的影像都是畫在bitmap
上的。 畫布有兩種: View
的原始畫布,也就是onDraw(Canvas canvas)
當中傳入的canvas
例項。- 人造畫布,即通過
saveLayer
或者new Canvas(Bitmap)
這些方法來人為新建一個畫布,saveLayer
新建一個畫布之後,以後所有的draw
函式所畫的影像都是在這個畫布上的,只有在restore、restoreToCount
函式以後,才會返回到原始畫布上繪製。 - 圖層
圖層是繪製的最小單元,每次呼叫
canvas.drawXXX
函式,都會生成一個專門的透明圖層來畫這個圖形,畫完之後,就蓋在了畫布上。連續呼叫draw
方法,那麼就會生成多個透明圖層,畫完之後依次在當前的畫布上顯示。
三、獲得Canvas
3.1 重寫View
中的函式 onDraw(Canvas canvas)
dispatchDraw(Canvas canvas)
在ViewGroup
中,當它有背景的時候呼叫onDraw
方法,否則會跳過onDraw
直接呼叫dispatchDraw
方法,在View
中,兩個都會呼叫的。
3.2 通過Bitmap
建立
Canvas c = new Canvas(bitmap);
//或者
Canvas c = new Canvas();
c.setBitmap(bitmap);
複製程式碼
如果我們通過這個方法構造了一個canvas
,那麼這個canvas
上繪製的影像會儲存在這個bitmap
上,而不是在View
上,如果想畫在View
上,就必須通過onDraw
函式傳進來的canvas
畫一遍。
3.3 SurfaceHolder.lockCanvas()
四、Canvas
變換
關於Canvas
的變換可以分為兩類:可逆變換和不可逆變換。
其中可逆變換包括:平移、旋轉、縮放和傾斜四種。
不可逆變換包括:裁剪。
4.1 可逆變換
4.1.1 平移
void translate(float dx, dy)
,向右和向下為正方向,此時移動的是canvas
原點的位置。
4.1.2 旋轉
rotate(float degrees, float px, float py)
,正數表示順時針旋轉,此外還可以指定旋轉的中心,預設是(0, 0)
4.1.3 縮放
scale(float sx, float sy, float px, py)
,對x
和y
進行縮放,並且可以指定縮放的中心點。
4.1.4 傾斜
skew(float sx, float sy)
,傾斜畫布,分別表示傾斜角度的tan
值。
4.2 不可逆變換
呼叫clipXXX
函式進行裁剪,通過與Rect、Path、Region
取交、並、差等集合運算來獲得最新的畫布狀態,這個操作是不可逆的,一旦canvas
被裁剪,那麼就不能被恢復。
#五、Canvas
繪製
5.1 繪製基本圖形
線
drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
drawLines(float[] pts, Paint paint)
drawLines(float[] pts, int offset, int count, Paint paint)
點
drawPoint(float x, float y, Paint paint)
drawPoints(float[] pts, Paint paint)
drawPoints(float[] pts, int offset, int count, Paint paint)
矩形
drawRect(float left, float top, float right, float bottom, Paint)
drawRect(RectF rect, Paint paint)
drawRect(Rect rect, Paint paint)
圓角矩形
drawRoundRect(RectF rect, float rx, float ry, Paint paint)
圓
drawCircle(float cx, float cy, float radius, Paint paint)
橢圓
drawOval(RectF oval, Paint paint)
扇形
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)
5.2 呼叫Path
繪製
在canvas
中,繪製路徑時使用drawPath(Path path, Paint paint)
方法
直線路徑
呼叫moveTo(float x, float y)
可以移動到某個繪製點,lineTo(float x, float y)
連到直線的結束點,如果連續畫了幾條直線,但沒有形成閉環,呼叫close()
會將路徑首尾連線起來。
矩形路徑
addRect(RectF rect, Path.Direction dir)
和drawRect(float l, float t, float r, float b, Path.Direction dir)
,用來繪製一條封閉的矩形路徑,第2個引數決定了該路徑的方向。
圓角矩形路徑
addRoundRect(RectF rect, float[] radii, Path.Direction dir)
和addRoundRect(RectF, float rx, float ry, Path.Direction dir)
圓形路徑
addCircle(float x, float y, float radius, Path.Direction dir)
橢圓路徑
addOval(RectF oval, Path.Direction dir)
弧形路徑
addArc(RectF oval, float startAngle, float sweepAngle)
5.3 繪製文字
canvas
的文字繪製提供以下3種:
普通水平繪製
drawText(String text, float x, float y, Paint paint)
指定各個文字位置
drawPosText(String text, float[] pos, Paint)
沿路徑繪製
drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)
,其中hOffset
表示與路徑起始點的水平偏移量,vOffset
表示與路徑中心的水平偏移量。