本文为学习Carson_Ho的文章《(3)自定义View Layout过程 - 最易懂的自定义View原理系列》所做的笔记,如需详细了解,移步(3)自定义View Layout过程 - 最易懂的自定义View原理系列
layout过程根据View类型
分2种情况
单一的View 仅计算本身View的位置
ViewGroup 计算自身View的位置,还需要确定子View在父容器中的位置
即 遍历调用所有子元素的measure() & 各子元素再递归去执行该流程
View树的位置是由包含的每个子视图的位置所决定
故若想计算整个View树的位置,则需递归计算每个子视图的位置
单一View的layout过程
具体流程:
layout过程的入口 = layout(),具体如下:
作用:确定View本身的位置,即设置View本身的四个顶点位置
layout()方法中:
1.确定View的位置:setFrame() / setOpticalFrame()
即初始化四个顶点的值、判断当前View大小和位置是否发生了变化 &返回
2.若视图的大小 & 位置发生变化
会重新确定该View所有的子View在父容器的位置:onLayout()
对于单一View的layout过程:由于单一View是没有子View的,故onLayout是一个空实现
对于ViewGroup的layout过程:由于确定位置与具体布局有关,所以onLayout()在ViewGroup为1个抽象方法,需重写实现。
ViewGroup的layout过程
步骤:
1.计算自身ViewGroup的位置:layout()
2.遍历子View & 确定自身子View在ViewGroup的位置(调用子View的layout()):onLayout()
需要注意的:
ViewGroup和View同样拥有layout()和onLayout(),但二者不同的:
一开始计算ViewGroup位置时,调用的是ViewGroup的layout()和onLayout();
当开始遍历子View & 计算子View位置时,调用的是子View的layout()和onLayout();
细节问题
getWidth() / getHeight():获得View最终的宽/高
getMeasuredWidth/getMeasuredHeight():获得View测量的宽/高
网上流传的错误的结论
实际上在当屏幕可包裹内容时,他们的值是相等的;
只有当view超出屏幕后,才能看出他们的区别:getMeasuredWidth()是实际View的大小,与屏幕无关,而getHeight的大小此时则是屏幕的大小。当超出屏幕后getMeasuredWidth()等于getWidth()加上屏幕之外没有显示的大小
结论
在非人为设置的情况下,View的最终宽/高(getWidth() / getHeight())
与 View的测量宽/高 (getMeasuredWidth() / getMeasuredHeight())永远是相等