转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52216195
- View树的Layout流程
- View的Layout时序图
-
View布局流程之Layout
- ViewGroup的Layout过程
- setFrame方法
- View的Layout过程
- FrameLayout的Layout过程
View树的Layout流程图:
View布局流程之Layout:
ViewGroup的Layout过程
view.getLeft()——mLeft:子View左边界到 父view左边界的距离
view.getTop()——mTop:子View上边界到父view上边界的距离
view.getRight()—mRight:子View右边界到父view右边界的距离
view.getBottom()—mBottom:子View下边距到父View下边界的距离
ViewGroup的onLayout过程:
是一个抽象方法,那么所有ViewGroup的子类都必须重写这个方法。在自定义ViewGroup控件中,onLayout配合onMeasure方法一起使用可以实现自定义View的复杂布局。自定义View首先调用onMeasure进行测量,然后调用onLayout方法动态获取子View和子View的测量大小,然后进行layout布局。重载onLayout的目的就是安排其children在父View的具体位置,重载onLayout通常做法就是写一个for循环调用每一个子视图的layout(l, t, r, b)函数,传入不同的参数l, t, r, b来确定每个子视图在父视图中的显示位置
setFrame方法:
- setFrame方法是一个隐藏方法,所以作为应用层程序员来说,无法重写该方法。该方法体内部通过比对本次的l、t、r、b四个值与上次是否相同来判断自身的位置和大小是否发生了改变。
- 如果发生了改变,将会调用invalidate请求重绘。
- 位置参数保存在mLeft,mTop,mRight,mBottom中。
- 如果大小发生了变化,onSizeChanged方法,该方法在大多数View中都是空实现,程序员可以重写该方法用于监听View大小发生变化的事件,在可以滚动的视图中重载了该方法,用于重新根据大小计算出需要滚动的值,以便显示之前显示的区域。
View的Layout过程:
这是一个空实现
FrameLayout的Layout过程:
首先,FrameLayout是继承ViewGroup的
onLayout()
layoutChildren()
上面getMeasuredWidth及getMeasuredHeight补充:
先看一张图:
-
getMeasuredWidth()、getMeasuredHeight()必须在onMeasure之后使用才有效,为什么?如果你没有测量,那你怎么得到这两个值,mMeasuredWidth及mMeasuredHeight就是在onMeasure中赋值的。顺便提下和我们经常用到getWidth(),getHeight()
- getWidth(): View在设定好布局后整个View的宽度。
- getMeasuredWidth():View上的內容进行测量后得到的View內容占的宽度
- view.getMeasuredHeight()可能隐藏在上头.可能在下头.如果view没有超出屏幕的时候view.getMeasuredHeight() 有可能小于 view.getHeight()
总结
layout也是从顶层DecorView向子View的递归调用view.layout方法的过程,即父View根据上一步measure子View所得到的布局大小和布局参数,将子View放在合适的位置上。具体有以下几点:
View.layout方法可被重载,ViewGroup.layout为final的不可重载,ViewGroup.onLayout为抽象的,子类必须重载实现自己的告诉父view layout过程。
measure操作完成后得到的是对每个View经测量过的measuredWidth和measuredHeight,layout操作完成之后得到的是对每个View进行位置分配后的mLeft、mTop、mRight、mBottom,这些值都是相对于父View来说的。
第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。
如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易