View工作流程之Measure
view的几个工作流程
- measure 负责测量控件以及子控件的尺寸信息
- layout 负责布局
- draw 负责绘制
measure流程的分类
我们知道,view可以分为两种类型,view以及viewgroup。
view的典型例子就是我们常见的TextView, ImageView等,
viewgroup指拥有子元素的布局,常见的就是我们熟悉的各种layout。
根据类型的不同,其measure流程也有不同。
View的measure流程
首先会调用view内部一个名叫measure的final方法,这个方法由于是final的,我们不能复写,但是其中调用了一个名叫onMeasure的方法,这是我们可以复写的。
先来看一个调用流程图
在onMeasure的源码中,我们可以看到,只有一个函数调用,那就是:
setMeasureDimension(getDefaultSize(getSuggestedMiniWidth(),widthMeasureSpec),
getDefaultSize(getSuggestedMiniHeight(),heightMeasureSpec));
setMeasureDimension方法会根据spaceMode和spacSize来确定大小,这两个参数都可以从MeasureSpec中解析获取。
可以看到内部又调用了一个getSuggestedMiniWidth()方法,在这个方法中,会根据是否有背景来确定View的最小尺寸,如果没有,那么最小宽/高就跟默认值一样,如果有,那么就跟背景的最小值相同。
如何获取默认值呢?这根据View的类型有所不同,有的View有默认值,有的View没有,正如书上所讲的一个例子,ShapeDrawable没有默认值,而BitmapDrawable有默认值。
ViewGroup的measure流程
在ViewGroup中,并没有重写onMeasure方法,但是有一个measureChildren方法,在该方法中会对每一个子元素进行measure。
在不同的ViewGroup子类中由于布局方式不同,所以onMeasure的实现也有所不同,所以ViewGroup并未对onMeasure方法做统一的实现。
measure过程和activity的生命周期并不是同步的
由于measure的过程和activity的生命周期并不是同步的,所以我们用一般的方法是不能在view还没有measure完毕之前在activity中获取其高度等信息的,如何解决呢,这里作者给出了四种方法。
1.复写onWindowFocusChanged方法,在该方法中,测量过程已经完成
2.使用view.post(runnable)方法
3.ViewTreeObserver的回调onGlobalLayout()方法
4.在View.measure中测量,但是此方法受到layoutparam的限制,在match_parent时无法使用