RelativeLayout源码解析
参考博客:
http://blog.csdn.net/wz249863091/article/details/51757069
RelativeLayout在measure的时候每次都一定会遍历2次,性能有所降低,在实际使用的时候,尽量减少布局嵌套层数
RelativeLayout作为一个ViewGroup的子类,主要起到的是一个容器的作用,所以在RelativeLayout源码中没有重载onDraw的方法又由于RelativeLayout内部的子view都是以相对关系存在的,所以只要计算出子view的坐标,就能知道每个子view该放在布局哪
在RelativeLayout的measure过程中,主要可以分为6个步骤
1.先把内部子view根据纵向关系和横向关系排序
2.初始化一些变量值
3.遍历水平关系的view
4.遍历竖直关系的view
5.baseline计算
6.宽度和高度修正个位置
基本概念
纵向关系:marginTop、marginBottom…
ABOVE, BELOW, ALIGN_BASELINE, ALIGN_TOP, ALIGN_BOTTOM
水平关系:marginLeft、marginRight…
LEFT_OF, RIGHT_OF, ALIGN_LEFT, ALIGN_RIGHT, START_OF, END_OF, ALIGN_START, ALIGN_END
dependents:依赖别人的;eg:a,b依赖c,那么c的dependents中存的是a,b
dependencies:被依赖的
onMeasure过程
DependencyGraph
sortChildren: 这个方法也很简单主要对左右关系和上下关系的view数组进行非空判断,然后用DependencyGraph 来完成排序,DependencyGraph 顾名思义,就是关系图的意思
add(): 有图就有节点,根据view生成一个节点,如果是一个有效id就把节点加到List当中
getSortedViews:排序算法
findRoots:找到不依赖别的view的view,作为root节点
初始化一些变量值
确定一下宽高
遍历水平关系的View
根据方向获得子view中设置的规则:int[] rules = params.getRules(layoutDirection);
把这些左右方向的规则转化成左右坐标:applyHorizontalSizeRules(params, myWidth, rules);
然后测算出水平方向的子view尺寸: measureChildHorizontal(child, params, myWidth, myHeight);
确定水平方向子view位置: if (positionChildHorizontal(child, params, myWidth, isWrapContentWidth)) {
offsetHorizontalAxis = true;
}
遍历垂直关系的View
计算baseline
宽度和高度修正
这部分代码比较好理解,在onMeasure()之前就提到
这里谷歌工程师也告诉我们了
在计算子分配子view的坐标时候,需要用到父view的尺寸
但是在完成下面这个操作之前,我们是无法拿到一个准确值
所以我们先用一个默认值代替
在计算完之后,我们再用偏移量去更新真实坐标
偏移量的计算公式是offset = DEFAULT_WIDTH - width
这里就是拿到准确的宽度和高度之后,对一些依赖父容器决定位置的子view重新做一次测量
然后根据gravity对偏移量再一次修正
然后如果是右到左显示,再做一次修改
整个onMeasure()过程就结束了