privatestaticintgetRootMeaureSpec(int windowSize, int rootDimension) { int measureSpec; switch (rootDimension) { case ViewGroup.LayoutParams.MATRCH_PARENT: // Window can't resize. Force root view to be windowSize. measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY); break; case ViewGroup.LayoutParams.WRAP_CONTENT: // Window can resize. Set max size for root view. measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST); break default: // Window wants to be an exact size. Force root view to be that size. measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY); break; } return measureSpec; }
// ViewGroup的measureChildWithMargins方法 protectedvoidmeasureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { finalMarginLayoutParamslp= (MarginLayoutParams) child.getLayoutParams();
switch (sepcMode) { // Parent has imposed an exact size on us case MeasureSpec.EXACTLY: if (childDimension >= 0) { resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } elseif (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size. So be it. resultSize = size; resultMode = MeasureSpec.EXACTLY; } elseif (childDimesion == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break;
// Parent has imposed a maximum size on us case MeasureSpec.AT_MOST: if (childDimension >= 0) { // Child wants a specific size... so be it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } elseif (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size, but our size is not fixed. // Constrain child to not be bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } elseif (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break;
// Parent asked to see how big we want to be case MeasureSpec.UNSPECIFIED: if (childDimension >= 0) { // Child wants a specific size... let him have it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } elseif (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size... find out how big it should be resultSize = 0; resultMode = MeasureSpec.UNSPECIFIED; } elseif (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size.... // find out how big it should be resultSize = 0; resultMode == MeasureSpec.UNSPECIFIED; } break; } return MeasureSpec.makeMeasureSpec(resultSize, resultMode); }
switch (specMode) { case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: case MeasureSpec.EXACTLY: result = sepcSize; break; } return result; }
protectedvoidonMeasure(int widthMeasureSpec, int hegithMeasureSpec) { if (mOrientation == VERTICAL) { measureVertical(widthMeasureSpec, heightMeasureSpec); } else { measureHorizontal(widthMeasureSpec, heightMeasureSpec); } }
// measureVertical核心源码 // See how tall everyone is. Also remember max width. for (inti=0; i < count; ++i) { finalViewchild= getVirtualChildAt(i); ... // Determine how big this child would like to be. If this or // previous children have given a weight, then we allow it to // use all available space (and we will shrink things later // if need) measureChildBeforeLayout( child, i, widthMeasureSpec, 0, heightMeasureSpec, totalWeight == 0 ? mTotalLength : 0);
if (oldHeight != Integer.MIN_VALUE) { lp.height = oldHeight; }
// ViewRootImpl.java privatevoidperformLayout(WindowManager.LayoutParams lp, int desiredWindowWidth, int desiredWindowHeight) { ... host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight()); ... }
// View.java publicvoidlayout(int l, int t, int r, int b) { ... // 通过setFrame方法来设定View的四个顶点的位置,即View在父容器中的位置 booleanchanged= isLayoutModeOptical(mParent) ? set OpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
... onLayout(changed, l, t, r, b); ... }
// 空方法,子类如果是ViewGroup类型,则重写这个方法,实现ViewGroup // 中所有View控件布局流程 protectedvoidonLayout(boolean changed, int left, int top, int right, int bottom) {
protectedvoidonlayout(boolean changed, int l, int t, int r, int b) { if (mOrientation == VERTICAL) { layoutVertical(l, t, r, b); } else { layoutHorizontal(l,) } }
// layoutVertical核心源码 voidlayoutVertical(int left, int top, int right, int bottom) { ... finalintcount= getVirtualChildCount(); for (inti=0; i < count; i++) { finalViewchild= getVirtualChildAt(i); if (child == null) { childTop += measureNullChild(i); } elseif (child.getVisibility() != GONE) { finalintchildWidth= child.getMeasureWidth(); finalintchildHeight= child.getMeasuredHeight();
final LinearLayout.LayoutParamslp= (LinearLayout.LayoutParams) child.getLayoutParams(); ... if (hasDividerBeforeChildAt(i)) { childTop += mDividerHeight; }