总结来自官方文档
首先Android里边的视图是以树形结构组织起来的。视图树的绘制是从视图的根节点开始的。这就要求去测量和绘制这个视图树时遍历视图树上的每一个View。每一个Viewgroup也相当于一个树,他也有责任保证他的每一个子View的Draw方法会被调用。同样的每一个子View也有责任绘制自己。因为树是按顺序遍历的,这意味着ViewGroup会在子View被绘制之前已近被绘制了。(View的大小是由上一级View约束的)
绘制布局是2个过程:一个测量过程一个布局过程。①测量过程是在measure(int, int)中实现的,并且这是一个自上而下的遍历视图树的过程。每一个View将尺寸信息递归的传递下去。在递归结束的时候,每一个View都设置了自己的尺寸信息。②第二个过程是布局(对于ViewGroup来说是确定子View的位置,对于自View来说就是绘制自己),调用layout(int, int, int, int)方法。
这也是一个自上而下的过程。在这个过程中,父View负责使用测量过程中传递下的的尺寸信息确定子View的位置。
当一个View对象的measure()方法返回之前,他的getMeasuredWidth() and getMeasuredHeight()
必须已经确定了。一个View的宽度和高度必须受到父View的强行限制。这样才能保证在measure()方法执行完的时候父View可以包含所有的子View。一个父View可能对子View多次调用measure()方法。例如:父View可能使用unspecified Mod来查探子View想要申请多大空间,如果子View的尺寸总和太大或者太小,然后会再调用一次measure()方法。
补充:
- Viewgroup必须重写他的measure(int, int)和layout(int, int, int, int)方法。这是应为ViewGroup直接继承自view,而View的measure方法是不会遍历子View的。所以,如果不重写measure方法,默认getMeasuredWidth()返回的0即measure方法传入的宽高是0,所以有些View是可能看不到的。然而对于继承自Linearlayout 的View,其measure方法默认会遍历子View,所以不需要手动调用子View 的layout方法。
getWidth()和getMeasuredWidth()的区别
getWidth(): View在设定好布局后,整个View的宽度
getMeasuredWidth():对View上的内容进行测量后得到的View内容占据的宽度。
很简单,getWidth()就是View显示之后的width,而getMeasuredWidth,从前面的源代码就可以看出来其实是在measure里面传入的参数,具体是否一样完全要看程序最后的计算