其实onMeasure()测量模式难明白是,你没有看源码我们可以看看ViewGroup是如何处理的
首先是测量模式
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
int specMode = MeasureSpec.getMode(spec);
int specSize = MeasureSpec.getSize(spec);
int size = Math.max(0, specSize - padding);
int resultSize = 0;
int resultMode = 0;
switch (specMode) {
// Parent has imposed an exact size on us
case MeasureSpec.EXACTLY:
if (childDimension >= 0) {
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size. So be it.
resultSize = size;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
break;
// Parent has imposed a maximum size on us
case MeasureSpec.AT_MOST:
if (childDimension >= 0) {
// Child wants a specific size... so be it
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size, but our size is not fixed.
// Constrain child to not be bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
break;
// Parent asked to see how big we want to be
case MeasureSpec.UNSPECIFIED:
if (childDimension >= 0) {
// Child wants a specific size... let him have it
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size... find out how big it should
// be
resultSize = 0;
resultMode = MeasureSpec.UNSPECIFIED;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size.... find out how
// big it should be
resultSize = 0;
resultMode = MeasureSpec.UNSPECIFIED;
}
break;
}
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
}
看一下代码测量的规则就很好懂了 ,测量模式是父控件和子控件一起决定的。
大家看看这个图片
测量的模式可以为以下三种:
1、EXACTLY
精确值模式,当我们将控件的layout width 属性或layout height 属性指定为具体数值时,
比如andorid:layout_ width="100dp", 或者指定为match_ parent 属性时(占据父View的大小),系统使用的是EXACTLY模式。
效果:父View决定自元素的确切大小,子View将被限定在给定的边界里而忽略它本身大小;
2、AT MOST
最大值模式,当控件的layout_ width 属性或layout_ height 属性指定为wrap_ content 时,
控件大小一一般随着控件的子控件或内容的变化而变化,此时控件的尺寸只要不超过父控件允许的最大尺寸即可。
效果:子View至多达到指定大小的值
3、UNSPECIFIED
自由模式, 不指定其大小测量模式,View想多大就多大。
效果:父View不给子View施加任何束缚,子View可以得到任意想要的大小
View类默认的onMeasure方法只支持EXACTLY模式,所以如果在自定义控件的时候不重写onMeasure方法的话,就只能使用EXACTLY模式。控件可以响应你指定的具体宽高值或者是match_ parent 属性。而如果要让自定义View支持wrap_ content 属性,那么就必须重写onMeasure()方法来指定wrap_ content 时的大小。
总结:想要子View得到测量模式,你要看看父VIew的测量模式的束缚规则,在规则之下你在去决定你的测量模式
部分引用:
1、有心课堂
2、Android群英传