作者博客
http://www.cherylgood.cn
前言
大家好!本次我们将继续学习Android之自定义View的死亡三部曲中的最后一部(Draw):画出最真实的自己
在此之前,我们在「Android之自定义View的死亡三部曲之Measure 」中分析了View测测量过程,获得了View的三围数据-测量后获得高和宽,在「Android之自定义View的死亡三部曲之Layout」 中分析了View的测量过程,经过测量后,我们就能拿到View的left、top、right、bottom四个点的值。那么我们剩下最后一步,将我的的View绘制出来。
绘制吧
Ok,这次我们依然是以ViewRootImpl的performTraversals方法起点。
这次我们分析到performDraw方法了。好的,我们一起来看下performDraw里面的代码吧,我只保留来于本次分析相关的关键代码。
看1处,既然有完全绘制,当然也会有局部绘制了,这样做是为了提高性能
OK,我们看下draw这个方法里面的代码
从上面的代码分析中,我们看到,最后时通过调用drawSoftware进行绘制,那么我们看下drawSoftware方法的代码
Ok,我们分析到第8步知道,最终调用了mView的draw开始绘制了,而mView也就是DecorView,我们前面分析过DecorView是一个FrameLayout,而FrameLayout并没有重现draw方法,ViewGroup也没有重写,所以,我们直接看View的draw方法,代码有点长,但是思路分清晰,官方给出的解释也是非常清晰的
OK,第2步和第5步是保存canves状态和恢复的操作,我们这次就分析其他步骤就好
首先,我们看第1步,在View非透明情况下,执行背景的绘制操作
从上面的分析,我有又个意外的发现,当scrllX或者scrollY的值不为0时,先使canvas偏移后在绘制,这就是为什么如果我们是使用Scoller来实现View的滑动时,实际上移动的是View的可视区域,而不是View本身
我们看下setBackgroundBounds里面是如何确认背景边界的
介绍完绘制背景,我们接下来分析绘制内容部分,我们看onDraw方法,没错,又是空的,因为这是我们在自定义View的时候需要自己去实现的
OK,那我们看下一步,传递绘制事件给child们
我们先看View的dispatchDraw,没错,还是空的,View就是最原始的了,哪里有child嘛。
那么我们来看ViewGroup中的吧,源码优点长,我保留于本次分析相关就好
ok,重点是drawChild这个方法,我们看下drawChild里面做什么操作
里面直接调用了child的draw方法。不过这个方法跟我们前面的分析的draw有点区别哦,没错,参数个数不同,那么我们看下到底却别在哪呢,这个方法的代码很长,我截取关键代码
上面主要做的事情就是,如果有cache,就利用cache进行绘制,没有则直接调用View的draw方法。然后根据前面的分析,最终会调用个个View的onDraw进行绘制操作
接下来到了第六部,绘制装饰物(例如recyclerView的滚动条),OK,我们来看下onDrawForeground方法
通过以上的分析,我们就把View的Draw分析完了
总结: