普通View的measure流程
2016-06-24 00:56
225 查看
对于普通的view,其测量在ViewGroup中的measureChildWithMargins函数中调用child view的measure开始测量。
1:从measure函数开始
官方关于此函数的说明:measure函数用来计算一个view的尺寸,其传入的参数为parentView对此view的宽/高限制信息。实际的尺寸测量将会调用onMeasure来完成,因此,子类必须重写onMeasure函数。
通过measure函数的源码我们也可以知道:首先,它是final的,所以不可以重写;其次,它主要是对传入的parentView的宽高限制信息进行了是否与上一次的相同的判断,若是相同则不调用onMeasure重新测量;
2:measure ——> onMeasure函数
通过其代码,我们可以知道主要用了这三个函数,我们一一分析:
2.1:getSuggestedMinimumWidth函数:返回android:minWidth和背景宽度二者之间的最大值
2.2:getDefaultSize:如果measureSpec没有限定则返回size,否则返回measureSpec中的size
到此:我们可以总结getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec)的逻辑:如果parentView对尺寸没有限制(即parentView的模式为UNSPECIFIED),那么将返回view的suggested最小值,否则返回parentView指定的尺寸。getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)类似。
2.3 setMeasuredDimension:很简单,设置测量的宽高(注意不是view实际的宽高,实际的宽高要等layout完成之后才确定,虽然几乎全部就是measure后的宽高)
至此,关于onMeasure函数分析结束。
===================================================================
http://www.cnblogs.com/willhua/
===================================================================
1:从measure函数开始
public final void measure(int widthMeasureSpec, int heightMeasureSpec) { 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 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函数用来计算一个view的尺寸,其传入的参数为parentView对此view的宽/高限制信息。实际的尺寸测量将会调用onMeasure来完成,因此,子类必须重写onMeasure函数。
通过measure函数的源码我们也可以知道:首先,它是final的,所以不可以重写;其次,它主要是对传入的parentView的宽高限制信息进行了是否与上一次的相同的判断,若是相同则不调用onMeasure重新测量;
2:measure ——> onMeasure函数
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }
通过其代码,我们可以知道主要用了这三个函数,我们一一分析:
2.1:getSuggestedMinimumWidth函数:返回android:minWidth和背景宽度二者之间的最大值
protected int getSuggestedMinimumWidth() { int suggestedMinWidth = mMinWidth; //mMinWidth对应android:minWidth属性所指定的值,如果它没有指定,那么默认为0 if (mBGDrawable != null) { //如果设置了背景 final int bgMinWidth = mBGDrawable.getMinimumWidth(); //背景的宽度,如果是ShapeDrawable那么为0,如果是BitmapDrawable则有原始宽高 if (suggestedMinWidth < bgMinWidth) { //如果设定的最小值小于背景图片宽度,那么设定最小值为背景图片宽度 suggestedMinWidth = bgMinWidth; } } return suggestedMinWidth; }
2.2:getDefaultSize:如果measureSpec没有限定则返回size,否则返回measureSpec中的size
public static int getDefaultSize(int size, int measureSpec) { int result = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = specSize; break; } return result; }
到此:我们可以总结getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec)的逻辑:如果parentView对尺寸没有限制(即parentView的模式为UNSPECIFIED),那么将返回view的suggested最小值,否则返回parentView指定的尺寸。getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)类似。
2.3 setMeasuredDimension:很简单,设置测量的宽高(注意不是view实际的宽高,实际的宽高要等layout完成之后才确定,虽然几乎全部就是measure后的宽高)
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { mMeasuredWidth = measuredWidth; mMeasuredHeight = measuredHeight; mPrivateFlags |= MEASURED_DIMENSION_SET; }
至此,关于onMeasure函数分析结束。
===================================================================
http://www.cnblogs.com/willhua/
===================================================================
相关文章推荐
- 将博客搬至CSDN
- 表数据拼接,表头和数据用"|"和"\n"分隔
- laravel数据库迁移
- 《构建之法》读书笔记
- Docker容器操作中常用命令集合
- 使用json web token
- Do you want to know me?----Come in.
- [Python Scrapy] Windows下BeautifulSoup安装
- android中的网络解析xml,json,html框架
- 机器学习学习笔记 PRML Chapter 1.2 : Probability Theory
- java中Map,List与Set的区别
- [HihoCoder]#1069 : 最近公共祖先·三
- [HihoCoder]#1067 : 最近公共祖先·二
- urlencode/base64/sha1/md5的区别
- 问题 E: 旋转加密
- 小程序分析(fork()和vfork())
- javaScript strict Mode and Window
- [HihoCoder]#1062 : 最近公共祖先·一
- Linux C 信号 pause、sigsuspend 的相同与区别
- 04_一个例子搞清数组和循环