自己通过阅读掘金文章简化的,详细的请看参考文献中的
class LinearLayout extends ViewGroup
abstract class ViewGroup extends View implements ViewParent, ViewManager
一. onMeasure
在测量过程中涉及到了MeasureSpec类,MeasureSpec是View的测量规则。它是int类型的(4字节32位的数据),前两位是SpecMode ,后30位是SpecSize。
SpecMode有三种类型:
- MeasureSpec.EXACTLY:精准模式,当width或height为具体dp值或为match_parent时。
- MeasureSpec.AT_MOST:最大模式,当width或height为wrap_content时。
- MeasureSpec.UNSPECIFIED:如ListView、ScrollView。
ViewGroup继承了View,View的measure()是final的,子类不能重写,但是它提供了onMeasure(),子类会重写onMeasure()。
- 如果继承ViewGroup,ViewGroup是抽象类,onMeasure()的具体实现在子类(LinearLayout等)中,LinearLayout中的onMeasure()会遍历child,调用child.measure(),然后判断child的子类。
- 如果是view,则测量出宽高。
二. onLayout
View类中的onLayout()是一个空方法,因为如果一个控件继承了View,它是没有子元素的,只需要确定自己的位置(ViewGroup继承View,它只需要确定自己的位置,确定好自己的位置后,在确定自己child的位置);
- View中layout()仅在ViewGroup中重写,ViewGroup中的layout()是final的。
- ViewGroup中的onLayout()是抽象方法,具体实现在子类(LinearLayout等)中;
- View的子类中没有layout()方法,只有onLayout()方法,因为在View中的layout()中就确定了自己的位置left、top、right、bottom,之后只需要在ViewGroup子类中遍历child,调用child.layout(),确定child的位置。
三. onDraw
View的draw:
- 首先会drawBackground(canvas)绘制背景色,该方法时private的;
- 然后是onDraw(canvas)绘制内容
- dispatchDraw(canvas)绘制child,如果子元素继承了ViewGroup,则再次循环调用dispatchDraw();
- 最后是onDrawForeground(canvas) 绘制装饰(前景、滚动条)
参考文献:
【1】View的绘制-measure流程详解
https://juejin.im/post/5cbdaa89f265da03914d6177
【2】View的绘制-layout流程详解
https://juejin.im/post/5cc170d7f265da035d0c7fed?utm_source=gold_browser_extension
【3】View的绘制-draw流程详解
https://juejin.im/post/5cc17280e51d4514df4206b4?utm_source=gold_browser_extension