简介
这篇文章继续就上一篇文章【View】- setContentView方法和UI绘制流程(源码分析)中performDraw方法进行讲解,了解UI绘制的布局过程。如果想了解测量流程,请查看【view】- 测量流程。
如果想了解测量流程,请查看【view】- 布局流程
performDraw
读过【View】- setContentView方法和UI绘制流程(源码分析)应该知道,performDraw中的mView是顶层布局DecorView。
private void performDraw() {
...
draw(fullRedrawNeeded);
...
}
获取mDirty,该值表示需要重绘的区域。
如果fullRedrawNeeded为真,则把dirty区域置为整个屏幕,表示整个视图都需要绘制。
if (fullRedrawNeeded) {
mAttachInfo.mIgnoreDirtyState = true;
dirty.set(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
}
通知注册的侦听器绘图过程即将开始
mAttachInfo.mTreeObserver.dispatchOnDraw();
调用drawSoftware方法,这个方法首先是实例化了Canvas对象,然后锁定该canvas的区域,由dirty区域决定,接着对canvas进行一系列的属性赋值,最后调用了mView.draw(canvas)方法,那么之前就讲过这里的mView就是我们的DectorView所以是从DectorView顶层开始绘制 那么之前的一切都是在进行准备一块画板具体的绘制实在mView.draw当中,这里将画板给入,而现在则是正式开始绘制流程。
调用DectorView的draw方法,先看一下View中draw方法的实现。
- 绘制背景
if (!dirtyOpaque) {
drawBackground(canvas);
}
标记位dirtyOpaque,该标记位的作用是判断当前View是否是透明的,如果View是透明的,那么根据下面的逻辑可以看出,将不会执行一些步骤,比如绘制背景、绘制内容等。这样很容易理解,因为一个View既然是透明的,那就没必要绘制它了 。
绘制总结
1、对View的背景进行绘制
2、保存当前的图层信息
3、绘制View的内容
if (!dirtyOpaque) onDraw(canvas);
onDraw,View中该方法是一个空实现,这里同理于之前的onMeasure和onLayout因为不同的View有着不同的内容,这需要我们自己去实现,即在自定义View中重写该方法来实现。
4、对View的子View进行绘制(如果有子View,会调用子View的draw(canvas, this, drawingTime)方法。
5、绘制View的褪色的边缘,类似于阴影效果
6、绘制View的装饰,比如foreground, scrollbars
7、在画布上绘制默认的焦点高光
具体实现请自己看代码,如果前面都能够看懂,那么相信也能大致看懂里面的执行过程。
网友评论