子View的MeasureSpec的值是由(子View的布局参数(LayoutParams)和父容器的MeasureSpec值)计算得来的,具体逻辑
/*
*@paramspec 父View的详细测量值
*@parampadding View当前尺寸的内边距和外边距
*@paramchildDimension 子视图的布局参数
*@returna MeasureSpec integer for the child
*/
public static intgetChildMeasureSpec(intspec, intpadding, intchildDimension)
根据View的类型measure过程主要分为两种情况
(1)单一View的measure过程
1. measure过程:该方法被final修饰,不可以被覆写
基本测量逻辑的判断(先判断是否是强制测量、测量模式改变了没有,再判断是否强制测量、忽略缓存)
if (是否强制测量 || 是否需要重新测量(测量模式有没有改变)) {
if (mMeasureCache缓存中没有取到值 || 是否忽略缓存) {
onMeasure();
}
}
2. onMeasure()过程:
setMeasureDimension()
getDefaultSize()
getSuggestedMinimumWidth()
因此:在自定义控件时候,如果没有重写onMeasure方法,同时给控件设置wrap_content属性时,控件默认会显示match_parent效果。
其中:
mMeasureCache中存储通过传入的widthMeasureSpec和heightMeasureSpec计算得出的key值信息,即view的信息。
(longkey = (long) widthMeasureSpec <<32| (long) heightMeasureSpec &0xffffffffL;)
mPrivateFlags用于记录了View的各种状态位。
(2)ViewGroup的measure过程
1. measureChildren()
for (遍历ViewGroup中的所有子View) {
if (View不是GONE状态) {
measureChild()
}
}
2.measureChild()
measureSpec = 通过getChildMeasureSpec()方法获取到当前Child的MeasureSpec的值
measure(measureSpec);
3. getChildMeasureSpec()
根据父布局的MeasureSpec和当前View的尺寸决定当前View的MeasureSpec
4. measure()
总结
单一View的measure过程与ViewGroup过程最大的不同:单一View对onMeasure()具有统一的实现,而ViewGroup没有
若LinearLayout的子View设置了weight,会进行两次measure计算,会比较耗时,所有当LinearLayout的子View需要使用weight的时候,最好替换成RelativeLayout布局
网友评论