本篇你将了解到:
- draw 的具体流程
- 简单的去重写 onDraw 方法
draw 方法
draw过程的主要流程如下:
- 绘制
background
- 如果需要的话,保存
canvas
的layer
,来准备fading
- 绘制
view
的content
(调用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 调用onDraw方法
if (!dirtyOpaque) onDraw(canvas);
// Step 4, draw the children
dispatchDraw(canvas);
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
}
其中标志位 dirtyOpaque
为 true
时,是不回去调用 onDraw
方法的。而 dirtyOpaque
其实是由 privateFlags
决定的。如果我们修改了 privateFlags
的值,就可以使重写 onDraw
被调用。
- 方法1:设置背景
设置背景的方法里会调用computeOpaqueFlags
重新设置privateFlags
。
public void setBackgroundDrawable(Drawable background) {
computeOpaqueFlags();
....省略一大段代码
computeOpaqueFlags();
....省略一点点代码
invalidate(true);
invalidateOutline();
}
- 方法2:调用
setWillNotDraw
方法
同样也是修改privateFlags
达到目的。
public void setWillNotDraw(boolean willNotDraw) {
setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
}
重写 onDraw
目标效果就是在上一章的 Layout 中,添加一个圆形图案。
image.png
关键代码:
var paint = Paint().let {
it.color = Color.YELLOW
it
}
/**
* 不设置 background 的话,不会调用该方法
*/
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 写的
总结
Android View 框架(1)-- LayoutInflater
Android View 框架(2)-- measure
Android View 框架(3)-- layout
Android View 框架(4)-- draw
网友评论