MeasureSpec约束是由父控件传递给子控件的,这个类的源码如下:
public static class MeasureSpec {
private static final int MODE_SHIFT = 30;
private static final int MODE_MASK = 0x3 << MODE_SHIFT;
/**
* 父控件不强加任何约束给子控件,它可以是它想要任何大小
*/
public static final int UNSPECIFIED = 0 << MODE_SHIFT;
/**
* 父控件已为子控件确定了一个确切的大小,孩子将被给予这些界限,不管子控件自己希望的是多大
*/
public static final int EXACTLY = 1 << MODE_SHIFT;
/**
* 父控件会给子控件尽可能大的尺寸
*/
public static final int AT_MOST = 2 << MODE_SHIFT;
/**
* 根据所提供的大小和模式创建一个测量规范
*/
public static int makeMeasureSpec(int size, int mode) {
if (sUseBrokenMakeMeasureSpec) {
return size + mode;
} else {
return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
}
/**
* 从所提供的测量规范中提取模式
*/
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
/**
* 从所提供的测量规范中提取尺寸
*/
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
...
}
从源码中我们知道,MeasureSpec其实就是尺寸和模式通过各种位运算计算出的一个整型值,它提供了三种模式,还有三个方法(合成约束、分离模式、分离尺寸)。在《Android自定义View(一、初体验)》(如果不太了解的可以参考这篇博客)这篇博客中,我们得到了这三种模式对应的意思和布局文件中的参数值的对应关系(父控件填充屏幕MATCH_PARENT的情况,如果其他情况,请参考下面getChildMeasureSpec方法的结果):
约束 | 布局参数 | 值 | 说明 |
---|---|---|---|
UNSPECIFIED(未指定) | 0 | 父控件没有对子控件施加任何约束,子控件可以得到任意想要的大小(使用较少)。 | |
EXACTLY(完全) | match_parent/具体宽高值 | 1073741824 | 父控件给子控件决定了确切大小,子控件将被限定在给定的边界里而忽略它本身大小。特别说明如果是填充父窗体,说明父控件已经明确知道子控件想要多大的尺寸了(就是剩余的空间都要了)栗子:碗柜最大的碗就这么大,菜有多少都只能盛到这个最大的碗里,盛不下的我就管不了了(吃掉或者倒掉) |
AT_MOST(至多) | wrap-content | -2147483648 | 子控件至多达到指定大小的值。包裹内容就是父窗体并不知道子控件到底需要多大尺寸(具体值),需要子控件自己测量之后再让父控件给他一个尽可能大的尺寸以便让内容全部显示但不能超过包裹内容的大小栗子:碗柜有各种大小的碗,菜少就拿小碗放,菜多就拿大碗放,但是不能浪费碗的容积,要保证碗刚好盛满菜 |