(首先声明,这篇文章是博主在 mooc 上学习了 hyman 的视频打造Android流式布局和热门标签后总结的小知识)
onLayout函数的作用
上一篇文章说到 onMeasure 函数会测量子 View 以及 ViewGroup 的宽高,而 onLayout 则是进一步确定子 View 在 ViewGroup 中的位置。
1 | /** |
onLayout 的参数表示这个 View 相对于父控件的位置,对于自定义 ViewGroup 而言,一般不会用到,我们暂时不管。
系统调用完 onMeasure 方法后,已经确定了 ViewGroup 以及内部子 View 的大小,之后会调用 onLayout 来摆放这些子 View。具体操作是通过遍历子 View 并调用 View.layout 方法
1 | /** |
函数说明指出,在 onLayout
方法中,我们应该调用每个子 View 的 layout
方法,让子 View 自动布局到所需要的位置。需要注意的是,我们在 onMeasure
中调用 measureChild
方法来测量各个子控件,但其实这个方法内部也是调用了子 View 的 measure
方法来实现的,这是一种常用的分治策略。layout
方法的四个参数的意义如下:
Parameters | |
---|---|
l |
Left position, relative to parent |
t |
Top position, relative to parent |
r |
Right position, relative to parent |
b |
Bottom position, relative to parent |
都是子 View 相对父控件的位置。因此,在 onLayout 中,我们只要根据我们的需求计算出子 View 的位置信息,并调用子 View 的 layout
方法即可。
可能有人会问 ViewGroup 的位置又怎么确定?当然是在 ViewGroup 的父控件中通过 onLayout
来调用 ViewGroup 的 layout
方法啦。
所以,onLayout 方法的重点自然是计算子 View 的位置啦,由于不同需求的计算方法是不一样的,这里贴上 FlowLayout
的 onLayout 实现,仅仅是一个模板作用
1 | // 按行的方式记录子View |
###getWidth()和getMeasureWidth()
在测量或布局的时候需要用到子 View 的宽高,但系统提供了两个获取宽高的方法(这里以宽度为例,高度类比):getWidth()
, getMeasureWidth()
。一开始博主傻傻分不清这两个函数到底有什么区别,后来看了郭霖的博客后豁然开朗Android视图绘制流程完全解析,带你一步步深入了解View(二)。getMeasureWidth()
是在 onMeasure()
之后得到的,而 getWidth()
则在 onLayout()
之后获得。简单来说,getMeasureWidth()
方法中的值是通过 setMeasuredDimension()
方法来进行设置的,而 getWidth()
方法中的值则是通过视图右边的坐标减去左边的坐标计算出来的。所以,如果正常设计的话,这两个函数返回的值应该是一样的。所谓正常设计就是说,View 需要多大的宽高我们就给它布局多大的空间。
比方说在调用 layout 的时候,如果传这样的参数:
1 | child.layout(0, 0, child.getMeasureWidth(), child.getMeasureHeight()); |
也就是说,我们尊重测量的时候,严格按测量的大小布局,这是两个函数等价。但如果这样传参:
1 | child.layout(0, 0, 200, 200); |
那我们之前的测量结果就没有用到,此时 getMeasureWidth()
依然是测量出的宽度,而 getWidth()
就变成了 200。