本篇文章不将View的宽高是怎么计算的,只讲MeasureSpec这个类的size和mode是怎么计算的。
1.measureSpec的形成
sUseBrokenMakeMeasureSpec是个boolean值,为true时使用老版本的方式生成measureSpec,为false时用新的方式生成measureSpec。不过得到的结果都是一样的。其中 MODE_MASK=11measureSpec是一个int型的变量,java中int型变量由4个字节(32bit)组成,其中高2位用来封装mode,mode一共有3种:
- UNSPECIFIED = 0 << MODE_SHIFT; 即: 00
000000 00000000 00000000 00000000
- EXACTLY = 1 << MODE_SHIFT; 即: 01
000000 00000000 00000000 00000000
- AT_MOST = 2 << MODE_SHIFT; 即: 10
000000 00000000 00000000 00000000
低30位用来封装size.
最终得到的结果为高2位的mode和低30位的size
2.getMode方法获取mode
000000 00000000 00000000 00000000
所以将32位的 measureSpec和11000000 00000000 00000000 00000000进行&运算,最终得到的肯定是measureSpec的高2位。比如生成measureSpec时传入
参数3,AT_MOST。那么measureSpec为10000000 00000000 00000000 00000101,
measureSpec & MODE_MASK=10000000 00000000 00000000 00000101 &
11
000000 00000000 00000000 00000000
=
10000000 00000000 00000000 00000000=AT_MOST可以看出,传入measureSpec后,measureSpec的低30位肯定全部为0,最终只剩下高2位。而measureSpec的高2位正好就是mode
3.getSize方法获取size
计算方法和getMode差不多,只是先将MODE_MASK取反,~MODE_MASK为00111111 11111111 11111111 11111111那结果可想而知,measureSpec和~MODE_MASK进行&运算,结果肯定为measureSpec的低30位了,因为高2位和00进行&运算肯定是00了总结:自定义View时会经常使用到MeasureSpec,通过它拿size或者mode,其实只是生成一个32位的int值,取其高2位或者低30位。提高了运行效率