曾经面试时,面试官问了一个View和Viewgroup的测绘顺序,当时答的不是特别完美,今天总结下具体的顺序!
可能有童鞋说多简单啊不就是onMeasure onSizeChanged onLayout onDraw,
………加入一个ViewGroup里面放置了三个View,请说出log输出的具体顺序,附加一条,ondraw方法是谁通知他开始绘制的,以及ondraw中的canvas来自哪里?
好的现在开始我们今天的探索,看起来简单,但是不确定的知识点就是没掌握的知识点,自己弄明白不要模棱两可,感觉简单,却又不确定,这不是一个成长的小白改有的状态!!
- 场景NO1,我们直接把activity的布局文件直接设置成我们的viewgroup,并且不给他设置任何背景色,里面也不要加入任何子view
Log输出如下,
我们可以看到只有一个viewgroup的时候,先执行了onMeasure,然后是onSizeChanged,然后是onlayout 确定自己的位置,因为没有任何绘制的东西所有没有触发ondraw,所以面对刚才那个问题,是不是发现onDraw并不是一定要执行的,但是上面三个方法确实要执行的.
- 场景NO2,我们给我们刚才的跟布局加一个background属性,这里大家都能猜到执行顺序了吧,除啦和刚才的顺序一致,那就是ondraw方法也被触发了,这里有个疑问点,是哪个方法触发ondraw的?
- 场景NO3,我们把背景色去掉,然后往里面加入一个子View.那么这回的执行顺序又是什么呢?
我们直接看下结果,
从log可以看到,当Viewgroup嵌套一个View的时候执行的顺序如下
=>>>>>View的onMeasure方法
=>>>>> ViewGroup的onMeasure方法
=>>>>>ViewGroup的onSizeChanged方法
=>>>>>View的onSizeChanged方法
=>>>>>View的onlayout方法确定自己在ViewGroup中的位置=>>>>>ViewGroup的onlayout方法确定自己的位置
=>>>>>View的ondraw方法绘制View
- 此时我们再当前的基础上给viewgroup加入背景色,以及view加入背景色
执行顺序接上面结果,如下我们看下绘制的顺序,
我们看到先执行了viewgroup的ondraw方法,又执行了view的ondraw方法
- 最后一个场景,我们往里面加入三个字view看下log输出,最后看下viewgroup和view一起的时候测量和绘制时怎么样的,大概在脑海里有个印象!
这是最后一个场景的预览图,我们可以根据之前的猜测下执行顺序
最后的log输出如下>>>>>>>>
这次我们的日志分组来看,
先执行onMeasure方法组,子view先执行,最后执行viewgroup的onMeasure
测绘结束后,执行onSizeChanged组,
这里需要注意的是,viewgroup先执行onSizeChanged方法,然后依次执行view的onSizeChanged方法,
然后就是onLayout组方法,
这一组先执行的是view的onlayout方法,然后是viewgroup的onLayout方法,
从上面的规律好像发现了什么,是不是猜到了最后ondraw的组的执行顺序,
那就是先执行viewgroup的onDraw.然后才是view的onDraw的方法..看下我们的预测怎么样!!
有没有,我们又猜对….到此view和viewgroup的侧绘方法顺序到此完毕
那么最后一个疑问请哪个大神帮忙回答下,ondraw方法中的canvas是从哪里来的,他的实质是什么,这个方法是哪个方法触发的,他的执行条件是什么?
ondraw里面的canvas经过群友指点,看View的源码中体现,是因为View里面有个一个静态内部类叫,AttachInfo,里面有一个mCanvas,
我们可以看到,canvas的来源是View中Attachinfo的静态内部类一个属性,
剩下的就是ondraw的触发了,源码只体现了,这个方法是一个protect方法,给子类自己实现的,但是我们自己定义完view后,他怎么样才能运行呢?是哪个方法执行完毕,或者是哪个事件触发的ondraw呢?
忘知情者,指点下!