android中View.measure方法的源码注解

来源:互联网 发布:手机淘宝客户端是什么 编辑:程序博客网 时间:2024/04/28 13:15

首先来看measure方法的源码注解:

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,因此采用此两种测量方式需要制定尺寸.

1 0
原创粉丝点击