由viewgroup傳參取得widthMeasureSpec,heightMeasureSpec
主要方法getChildMeasureSpec(parentWidthMeasureSpec,...)
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 | /** * 遍歷ViewGroup中所有的子控制項,呼叫measuireChild測量寬高 */ protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) { final int size = mChildrenCount; final View[] children = mChildren; for (int i = 0; i < size; ++i) { final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) != GONE) { //測量某一個子控制項寬高 measureChild(child, widthMeasureSpec, heightMeasureSpec); } } } /** * 測量某一個child的寬高 */ protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) { final LayoutParams lp = child.getLayoutParams(); //取得子控制項的寬高約束規則 final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight, lp.width); final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop + mPaddingBottom, lp.height); child.measure(childWidthMeasureSpec, childHeightMeasureSpec); } /** * 測量某一個child的寬高,考慮margin值 */ protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); //取得子控制項的寬高約束規則 final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin + widthUsed, lp.width); final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin + heightUsed, lp.height); //測量子控制項 child.measure(childWidthMeasureSpec, childHeightMeasureSpec); |
UNSPECIFIED:不對View大小做限制,如:ListView,ScrollView(可以造成height出現UNSPECIFIED模式)
EXACTLY:確切的大小,如:100dp或者march_parent
AT_MOST:大小不可超過某數值,如:wrap_content
width取值(textview部分原始碼)
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 | //EXACTLY模式下 if (widthMode == MeasureSpec.EXACTLY) { // Parent has told us how big to be. So be it. width = widthSize; } //其他兩種模式走下面邏輯 else { if (mMaxWidthMode == EMS) { width = Math.min(width, mMaxWidth * getLineHeight()); } else { width = Math.min(width, mMaxWidth); } if (mMinWidthMode == EMS) { width = Math.max(width, mMinWidth * getLineHeight()); } else { width = Math.max(width, mMinWidth); } // Check against our minimum width width = Math.max(width, getSuggestedMinimumWidth()); //AT_MOST模式 if (widthMode == MeasureSpec.AT_MOST) { width = Math.min(widthSize, width); } } |
height取值(textview部分原始碼)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //EXACTLY模式下 if (heightMode == MeasureSpec.EXACTLY) { // Parent has told us how big to be. So be it. height = heightSize; mDesiredHeightAtMeasure = -1; } //其他兩種模式走下面邏輯 else { int desired = getDesiredHeight(); height = desired; mDesiredHeightAtMeasure = desired; //AT_MOST模式 if (heightMode == MeasureSpec.AT_MOST) { height = Math.min(desired, heightSize); } } |
總結,EXACTLY模式下失效,直接取設定大小;AT_MOST模式下失效,取三者(最大值,最小值,確切值)最小;
UNSPECIFIED模式下有效