1,view的测量:
measure()方法被父view调用,在measure中做一些初始化工作后,调用onmeasure()来进行实际自我测量,view的measure方法是final的不能够重写,所以主要逻辑都在onmeasure里(),onmeasure做的事,view和viewgroup做的不一样。
view的onmeasure()会计算出自己的尺寸然后保存,直接继承view的自定义控件需要重写onmeasure并设置wrap_content时自身的大小,否则就相当于是match_parent(这里就有测量时一个measurespec的概念,子view会结合父view的measurespec计算自己的measurespec)。
viewgroup的onmeasure()会调用所有子view的measure()让他们自己测量,然后根据子view计算的期望尺寸,算出他们的实际尺寸进行保存,同时也会根据子view的尺寸来确定下来自己的尺寸。
2,view的布局:
layout()方法被父view调用,在layout()中保存view传递进来的位置和尺寸,然后调用onlayout()进行实际的内部布局,onlayout()做的事view和viewgroup不一样
view:没有子view,所以view的onlayout()什么也不做。
viewgroup:viewgroup在onlayout中调用自己所有子view的layout()方法,把尺寸和位置传给他们,让他们完成自我布局。
总结就是,layout确定view本身的位置,onlayout确定所有子view的位置。
3,view的绘制:
draw方法是总调度方法,view的整个绘制流程都发生在draw里,一个完整的绘制流程包含,绘制背景(drawbackground),绘制自己的主体(onDraw)
绘制子view(dispatchDraw),绘制滑动条或者前景(drawforeground)。
view 绘制过程的传递是通过dispatchdraw实现,dispatchdraw遍历所有子元素的draw方法,这样draw事件就一层一层传递下去了。
参考:
自定义View,有这一篇就够了 - 简书
GitHub - chenzongwen/MiClockView(一个闹钟的实际例子)
Android 自定义 View 合集 - Android - 掘金
深入理解Android之View的绘制流程