View-MeasuerSepc
MeasuerSepc 是View 的一个内部类,在分析View 的测量(measuer)会出现这个类,这里先记录一下对MeasuerSepc的理解.
MeasuerSepc可以理解为 一个32位的int 值,其中前2位表示mode(模式),后30位表示size(具体大小),通过将mode和size体现在一个int值里面来避免过多的对象内存分配. MeasuerSepc同时提供了来makeMeasureSpec(int size,int mode) 来打包出来一个32位的int值.当然也有根据一个MeasuerSepc值来解包获取mode和size的方法.方便是getMode(int measureSpec)和getSize(int measureSpec) .
注意: MeasuerSepc代表的int值并不是MeasuerSepc自己本身.
具体源码看下面,红色部分是注释.(Android L的源码)
public static class MeasureSpec {
private static final int MODE_SHIFT = 30;
/**
* 11 0000...(30个0)
*/
private static final int MODE_MASK = 0x3 << MODE_SHIFT;
/**
* Measure specification mode: The parent has not imposed any constraint
* on the child. It can be whatever size it wants.父容器不对View做限制,想要多大就多大
*/
public static final int UNSPECIFIED = 0 << MODE_SHIFT;//00 000...(32个0)
/**
* Measure specification mode: The parent has determined an exact size
* for the child. The child is going to be given those bounds regardless
* of how big it wants to be.父容器已经精确的检测出view的大小,View最终的大小就是由
MeasureSpec的size决定.对应LayoutParams中 * 的match_parent和具体数值2种模式*/
public static final int EXACTLY = 1 << MODE_SHIFT;//0
1 0000...(30个0)/**
* Measure specification mode: The child can be as large as it wants up
* to the specified size.父容器给了一个最大值,View的大小不能超过这个值.它对应于
LayoutParams中的warp_content.*/
public static final int AT_MOST = 2 << MODE_SHIFT;
//10
0000...(30个0)public static int makeMeasureSpec(int size, int mode) {//创建一个MeasureSpec的int值:32位(前2位表示mode,后面30位表示size)
if (sUseBrokenMakeMeasureSpec) {//JB之前的版本
return size + mode;
} else {
return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
}
/**
* Extracts the mode from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the mode from
* @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
* {@link android.view.View.MeasureSpec#AT_MOST} or
* {@link android.view.View.MeasureSpec#EXACTLY}
*/
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
/**
* Extracts the size from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the size from
* @return the size in pixels defined in the supplied measure specification
*/
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
static int adjust(int measureSpec, int delta) {
final int mode = getMode(measureSpec);
if (mode == UNSPECIFIED) {
// No need to adjust size for UNSPECIFIED mode.
return makeMeasureSpec(0, UNSPECIFIED);
}
int size = getSize(measureSpec) + delta;
if (size < 0) {
Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
") spec: " + toString(measureSpec) + " delta: " + delta);
size = 0;
}
return makeMeasureSpec(size, mode);
}
- //.......
}