MeasureSpec是View的一个静态内部类,它通过将SpecMode和SpecSize打包成一个int值来避免过多的对象内存分配,并提供了打包和解包方法
MeasureSpec代表一个32位int值,高2位代表SpecMode,低30位代表SpecSize,SpecMode是指测量模式,而SpecSize是指在某种测量模式下的规格大小。
其部分代码如下:
public class View implements ... {
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);
}
}
}```
SpecMode有三类,每一类都表示特殊的含义,如下所示:
* UNSPECIFIED
父容器不对View有任何限制,要多大给多大,这种情况一般用于系统内部,表示一种测量状态
* EXACTLY
父容器已经检测出View所需要的精确大小,这个时候View的最终大小就是SpecSize所指定的值。它对应于LayoutParams中的match_parent和具体的数值这两种模式。
* AT_MOST
父容器指定了一个可用大小即SpecSize,View的大小不能大于这个值,具体是什么要看不同View的具体实现。它对应于LayoutParams中的wrap_content。
**View提供了一个有用的方法View.resolveSize(size, measureSpec)**
它是用来计算自身期望值和父视图提供值在模式下应该拥有的值
public class View implements ... {
public static final int MEASURED_SIZE_MASK = 0x00ffffff;
public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
public static final int MEASURED_STATE_MASK = 0xff000000;
public static int resolveSize(int size, int measureSpec) {
return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
}
public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
final int specMode = MeasureSpec.getMode(measureSpec);
final int specSize = MeasureSpec.getSize(measureSpec);
final int result;
switch (specMode) {
case MeasureSpec.AT_MOST:
if (specSize < size) {
result = specSize | MEASURED_STATE_TOO_SMALL;
} else {
result = size;
}
break;
case MeasureSpec.EXACTLY:
result = specSize;
break;
case MeasureSpec.UNSPECIFIED:
default:
result = size;
}
return result | (childMeasuredState & MEASURED_STATE_MASK);
}
}```
下面用一张表展示View的MeasureSpec创建规则(注:parentSize是指父容器中目前可使用的大小):
普通View的MeasureSpec 的创建规则
网友评论