MeasureSpec是View的一個靜態(tài)內(nèi)部類图呢,它通過將SpecMode和SpecSize打包成一個int值來避免過多的對象內(nèi)存分配,并提供了打包和解包方法
MeasureSpec代表一個32位int值,高2位代表SpecMode,低30位代表SpecSize磕谅,SpecMode是指測量模式,而SpecSize是指在某種測量模式下的規(guī)格大小宠纯。
其部分代碼如下:
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有任何限制征椒,要多大給多大,這種情況一般用于系統(tǒng)內(nèi)部湃累,表示一種測量狀態(tài)
* EXACTLY
父容器已經(jīng)檢測出View所需要的精確大小,這個時候View的最終大小就是SpecSize所指定的值碍讨。它對應(yīng)于LayoutParams中的match_parent和具體的數(shù)值這兩種模式治力。
* AT_MOST
父容器指定了一個可用大小即SpecSize,View的大小不能大于這個值勃黍,具體是什么要看不同View的具體實現(xiàn)宵统。它對應(yīng)于LayoutParams中的wrap_content。
**View提供了一個有用的方法View.resolveSize(size, measureSpec)**
它是用來計算自身期望值和父視圖提供值在模式下應(yīng)該擁有的值
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創(chuàng)建規(guī)則(注:parentSize是指父容器中目前可使用的大小):
普通View的MeasureSpec 的創(chuàng)建規(guī)則