本篇你將了解到:
- draw 的具體流程
- 簡(jiǎn)單的去重寫 onDraw 方法
draw 方法
draw過程的主要流程如下:
- 繪制
background - 如果需要的話,保存
canvas的layer,來準(zhǔn)備fading - 繪制
view的content(調(diào)用onDraw方法) - 繪制
children(dispatchDraw方法) - 如果需要的話,繪制
fading edges,然后還原layer - 繪制裝飾器、比如
scrollBar
下方是偽代碼,
public void draw(Canvas canvas) {
final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
(mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
// Step 3, draw the content 調(diào)用onDraw方法
if (!dirtyOpaque) onDraw(canvas);
// Step 4, draw the children
dispatchDraw(canvas);
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
}
其中標(biāo)志位 dirtyOpaque 為 true 時(shí),是不回去調(diào)用 onDraw 方法的。而 dirtyOpaque 其實(shí)是由 privateFlags 決定的。如果我們修改了 privateFlags 的值,就可以使重寫 onDraw 被調(diào)用。
- 方法1:設(shè)置背景
設(shè)置背景的方法里會(huì)調(diào)用computeOpaqueFlags重新設(shè)置privateFlags。
public void setBackgroundDrawable(Drawable background) {
computeOpaqueFlags();
....省略一大段代碼
computeOpaqueFlags();
....省略一點(diǎn)點(diǎn)代碼
invalidate(true);
invalidateOutline();
}
- 方法2:調(diào)用
setWillNotDraw方法
同樣也是修改privateFlags達(dá)到目的。
public void setWillNotDraw(boolean willNotDraw) {
setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
}
重寫 onDraw
目標(biāo)效果就是在上一章的 Layout 中,添加一個(gè)圓形圖案。

image.png
關(guān)鍵代碼:
var paint = Paint().let {
it.color = Color.YELLOW
it
}
/**
* 不設(shè)置 background 的話,不會(huì)調(diào)用該方法
*/
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val x = measuredWidth / 2.0F
val y = measuredHeight / 2.0F
canvas?.drawCircle(x, y, Math.min(x, y), paint)
}
全部代碼 -- AViewGroup:Github 地址,是 kotlin 寫的
總結(jié)
Android View 框架(1)-- LayoutInflater
Android View 框架(2)-- measure
Android View 框架(3)-- layout
Android View 框架(4)-- draw