图文概览 View测量流程
measure
性质:final方法,View测量初始方法
作用:基本逻辑计算,是否重新测量,调用onMeasure,缓存测量规格
onMeasure
性质:测量方法,子类可复写实现自己的测量方式
作用:进行测量规格计算,调用getDefaultSize和setMeasureDimension
getDefaultSize
setMeasureDimension
View测量规格参考:View.MeasureSpec分析
ViewGroup测量大概流程
源码分析 View.measure流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 // view measure入口, final类型 public final void measure(int widthMeasureSpec, int heightMeasureSpec) { // 是否需要再次计算等计算 ... if (cacheIndex < 0 || sIgnoreMeasureCache) { // 计算视图大小 onMeasure(widthMeasureSpec, heightMeasureSpec); mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; }else { setMeasuredDimensionRaw((int) (value >> 32), (int) value); } } protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 存储测量后的View宽 / 高 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); } // View的宽度为mMinWidth和mBackground.getMinimumWidth()中的最大值,高度类似 protected int getSuggestedMinimumWidth() { return (mBackground == null) ? mMinWidth : max(mMinWidth,mBackground.getMinimumWidth()); } // 根据View宽/高的测量规格计算View的宽/高值 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; // 模式为AT_MOST,EXACTLY时,使用View测量后的宽/高值 = measureSpec中的Size case MeasureSpec.AT_MOST: case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = specSize; break; } return result; } // 存储测量后的View宽 / 高 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { boolean optical = isLayoutModeOptical(this); if (optical != isLayoutModeOptical(mParent)) { Insets insets = getOpticalInsets(); int opticalWidth = insets.left + insets.right; int opticalHeight = insets.top + insets.bottom; measuredWidth += optical ? opticalWidth : -opticalWidth; measuredHeight += optical ? opticalHeight : -opticalHeight; } setMeasuredDimensionRaw(measuredWidth, measuredHeight); } private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) { mMeasuredWidth = measuredWidth; mMeasuredHeight = measuredHeight; mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET; }
ViewGroup.onMeasure 参考:Android图形系统—View之LinearLayout.measure分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // ViewGroup 继承类,大体都要充写次方法,大体模式如下 // 遍历子View,对子控件一一measure for(int i=0;i<size;++i){ measureChild(child, widthMeasureSpec, heightMeasureSpec) } // 合并所有子控件大小,计算出父控件宽高测量规格 mergeChildSpec() ; // 也有可能与第一步同时计算 // 设置父控件的宽/高值 setMeasuredDimension(widthMeasure, heightMeasure); }