android中View.measure方法的源码注解
2015-12-04 11:56
489 查看
首先来看measure方法的源码注解:
measure函数有2个参数,widthMeasureSpec 和 heightMeasureSpec。
onMeasure(widthMeasureSpec, heightMeasureSpec)方法:
当我们重写onMeasure时,需要调用setMeasuredDimension来设置自身的mMeasuredWidth和mMeasuredHeight,否则,就会抛出上面那个异常
setMeasuredDimension方法:类似于执行setter方法
计算都是在getDefaultSize函数里实现的:
关于getSuggestedMinimumHeight()
关于MeasureSpec的源码解析:
测量总结:
measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED)即measure(0,0)返回getSuggestedMinimumWidth()
如果采用MeasureSpec.AT_MOST或者
则舍弃getSuggestedMinimumWidth()得到的尺寸,返回int
specSize =MeasureSpec.getSize(measureSpec);的值MeasureSpec.EXACTLY;这是传入measure()的measureSpec参数,是mode+size,因此采用此两种测量方式需要制定尺寸.
public final void measure(int widthMeasureSpec, int heightMeasureSpec) { //判断旧的mOldWidthMeasureSpec 是否与新的测量方式相同,只要有一个不同就要重新测量 //对widthMeasureSpec的理解: if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT || widthMeasureSpec != mOldWidthMeasureSpec || heightMeasureSpec != mOldHeightMeasureSpec) { // first clears the measured dimension flag //清除标志位,"先取反,后与" :与是为了取被与的值 mPrivateFlags &= ~MEASURED_DIMENSION_SET; if (ViewDebug.TRACE_HIERARCHY) { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE); } // measure ourselves, this should set the measured dimension flag back //开始测量 onMeasure(widthMeasureSpec, heightMeasureSpec); // flag not set, setMeasuredDimension() was not invoked, we raise // an exception to warn the developer //通过标志位判断是否执行了setMeasuredDimension()方法 if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) { throw new IllegalStateException("onMeasure() did not set the" + " measured dimension by calling" + " setMeasuredDimension()"); } mPrivateFlags |= LAYOUT_REQUIRED; } //将重新为旧的值赋值 mOldWidthMeasureSpec = widthMeasureSpec; mOldHeightMeasureSpec = heightMeasureSpec; }
measure函数有2个参数,widthMeasureSpec 和 heightMeasureSpec。
onMeasure(widthMeasureSpec, heightMeasureSpec)方法:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //执行setMeasuredDimension方法 //参数解释: setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }
当我们重写onMeasure时,需要调用setMeasuredDimension来设置自身的mMeasuredWidth和mMeasuredHeight,否则,就会抛出上面那个异常
setMeasuredDimension方法:类似于执行setter方法
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { //将测量结果赋值 mMeasuredWidth = measuredWidth; mMeasuredHeight = measuredHeight; //添加flag,MEASURED_DIMENSION_SET mPrivateFlags |= MEASURED_DIMENSION_SET; }
计算都是在getDefaultSize函数里实现的:
//参数解析:size:大小 //measureSpec:是一个复合的标志位 public static int getDefaultSize(int size, int measureSpec) { //measureSpec是一个复合的概念:二进制表示:最前的2两位表示:mode;后30位表示尺寸 //关于mode:MeasureSpec.UNSPECIFIED这个是未执行大小:对应于wrap_content //MeasureSpec.AT_MOST:对应match_parent和fill_parent //MeasureSpec.EXACTLY:代表确切尺寸 int result = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { //未指定大小的情况下:返回建议的尺寸 case MeasureSpec.UNSPECIFIED: result = size; break; //AT_MOST,EXACTLY则返回按照mode测量的尺寸. case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = specSize; break; } return result; }
关于getSuggestedMinimumHeight()
protected int getSuggestedMinimumHeight() { //判断是否有背景,没有的话返回mMinHeight 即控件的最小高度(通过属性获取的) //如果背景不为空,则返回mMinHeight 或mBackground.getMinimumHeight() return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight()); }
关于MeasureSpec的源码解析:
public static class MeasureSpec { //设置mode的移位数 private static final int MODE_SHIFT = 30; private static final int MODE_MASK = 0x3 << MODE_SHIFT; //UNSPECIFIED为32个0 public static final int UNSPECIFIED = 0 << MODE_SHIFT; //EXACTLY为:01+30个0 public static final int EXACTLY = 1 << MODE_SHIFT; //AT_MOST为:10+30个0 public static final int AT_MOST = 2 << MODE_SHIFT; public static int makeMeasureSpec(int size, int mode) { //组建复合的measureSpec return size + mode; } public static int getMode(int measureSpec) { //取出mode return (measureSpec & MODE_MASK); } public static int getSize(int measureSpec) { //去除mode,获取size return (measureSpec & ~MODE_MASK); } }
测量总结:
measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED)即measure(0,0)返回getSuggestedMinimumWidth()
如果采用MeasureSpec.AT_MOST或者
则舍弃getSuggestedMinimumWidth()得到的尺寸,返回int
specSize =MeasureSpec.getSize(measureSpec);的值MeasureSpec.EXACTLY;这是传入measure()的measureSpec参数,是mode+size,因此采用此两种测量方式需要制定尺寸.
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories