首先把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;
上面的是定义了一些常亮,最后3个我们非常熟悉,就是我们常用的3种测量模式。前两个是做变换用的两个常亮,后面分析会提到这两个常亮的作用。
我们常用的两个方法:
// 将size和mode合成一个32位的int值
public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode) {
if (sUseBrokenMakeMeasureSpec) {
return size + mode;
} else {
return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
}
// 拆解出来mode
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
// 拆解出来size
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
先看makeMeasureSpec
方法,这是将一个size和一个mode组合成一个int值,方法的实现中有一个判断sUseBrokenMakeMeasureSpec
值得操作,这个值是什么呢,源码是这样写的:
/**
* Use the old (broken) way of building MeasureSpecs.
*/
private static boolean sUseBrokenMakeMeasureSpec = false;
// 在View的构造函数中sUseBrokenMakeMeasureSpec是这样初始化的
sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
假设我们的size的值是10,用二进制表示则是:
0000 0000 0000 0000 0000 0000 0000 1010
我们用的mode是EXACTLY
,二进制表示是:
0100 0000 0000 0000 0000 0000 0000 0000
1 我们先分析sUseBrokenMakeMeasureSpec == false
的情况,也就是当前系统版本大于JELLY_BEAN_MR1
:
这时返回值是return (size & ~MODE_MASK) | (mode & MODE_MASK)
这个东西具体怎么计算的呢?
在java中,int在内存中占用32位的长度,结合前面的定义:
MODE_SHIFT = 30
MODE_MASK = 0x3 << MODE_SHIFT;
0X3用二进制数表示是
0000 0000 0000 0000 0000 0000 0000 0011
,左移30位之后变成了
1100 0000 0000 0000 0000 0000 0000 0000
这是MODE_MASK
的值
那么~MODE_MASK
的值是按位取反后变成了:
0011 1111 1111 1111 1111 1111 1111 1111
size & ~MODE_MASK
按位与的值是:
0000 0000 0000 0000 0000 0000 0000 1010
。
同理我们可以计算出(mode & MODE_MASK)
的值是:
0100 0000 0000 0000 0000 0000 0000 0000
(size & ~MODE_MASK) | (mode & MODE_MASK)
的值是:
0100 0000 0000 0000 0000 0000 0000 1010
2 我们在分析sUseBrokenMakeMeasureSpec == true
的情况:
这时方法返回的是size + mode
,mode转化为10进制的值是1073741824,加上我们的size(10)是1073741834,转为二进制是:
0100 0000 0000 0000 0000 0000 0000 1010
可以看出和我们上面分析的结果是一样的,上面的方式其实就是在求和。至于为什么会分成两种情况,目前我也不清楚,有高手知道可以留言。
下面分析getMode
方法,返回值是measureSpec & MODE_MASK
,我们上面计算的结果是:
0100 0000 0000 0000 0000 0000 0000 1010
MODE_MASK
是
1100 0000 0000 0000 0000 0000 0000 0000
按位与后是
0100 0000 0000 0000 0000 0000 0000 0000
,就是我们的mode。
同理可以分析getSize
方法,返回值是measureSpec & ~MODE_MASK
,是
0100 0000 0000 0000 0000 0000 0000 1010
与
0011 1111 1111 1111 1111 1111 1111 1111
按位与
得到的就是
0000 0000 0000 0000 0000 0000 0000 1010
,就是10的二进制表示方式
以上就是全部内容,总体没有什么大的难度,就是位运算,位运算明白了就透彻了。