下面来看看 View 默认的onMeasure 方法:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }
public static class MeasureSpec { private static final int MODE_SHIFT = 30;// 移动的位数 private static final int MODE_MASK = 0x3 << MODE_SHIFT;// mask 0011 向右移动30位 public static final int UNSPECIFIED = 0 << MODE_SHIFT;// 0000 向右移动30位 public static final int EXACTLY = 1 << MODE_SHIFT;// 0001向右移动30位 public static final int AT_MOST = 2 << MODE_SHIFT;// 0010向右移动30位 // 向要知道 是什么模式可以调用: public static int getMode(int measureSpec) { return (measureSpec & MODE_MASK); } // 获取具体尺寸 public static int getSize(int measureSpec) { return (measureSpec & ~MODE_MASK); } // 自己 做一个这个int 数据, 传入 尺寸 和 模式就好了 public static int makeMeasureSpec(int size, int mode) { if (sUseBrokenMakeMeasureSpec) { return size + mode; } else { return (size & ~MODE_MASK) | (mode & MODE_MASK); } } }
父视图能力尺寸 |
子视图期望尺寸 |
子视图最终允许尺寸 |
EXACTLY + Size1
|
EXACTLY + Size2
|
EXACTLY + Size2
|
EXACTLY + Size1
|
fill_parent/match_parent
|
EXACTLY
+Size1
|
EXACTLY + Size1
|
wrap_content
|
AT_MOST
+Size1
|
AT_MOST
+Size1
|
EXACTLY + Size2
|
EXACTLY
+Size2
|
AT_MOST
+Size1
|
fill_parent/match_parent
|
AT_MOST
+Size1
|
AT_MOST
+Size1
|
wrap_content
|
AT_MOST
+Size1
|
UNSPECIFIED+Size1
|
EXACTLY + Size2
|
EXACTLY + Size2
|
UNSPECIFIED+Size1
|
fill_parent/match_parent
|
UNSPECIFIED+0
|
UNSPECIFIED+Size1
|
wrap_content
|
UNSPECIFIED+0
|
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (mOrientation == VERTICAL) { layoutVertical(); } else { layoutHorizontal(); } } void layoutVertical() { final int paddingLeft = mPaddingLeft; int childTop; int childLeft; // Where right end of child should go final int width = mRight - mLeft; int childRight = width - mPaddingRight; // Space available for child int childSpace = width - paddingLeft - mPaddingRight; final int count = getVirtualChildCount(); final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK; final int minorGravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK; switch (majorGravity) { case Gravity.BOTTOM: // mTotalLength contains the padding already childTop = mPaddingTop + mBottom - mTop - mTotalLength; break; // mTotalLength contains the padding already case Gravity.CENTER_VERTICAL: childTop = mPaddingTop + (mBottom - mTop - mTotalLength) / 2; break; case Gravity.TOP: default: childTop = mPaddingTop; break; } for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); if (child == null) { childTop += measureNullChild(i); } else if (child.getVisibility() != GONE) { final int childWidth = child.getMeasuredWidth(); final int childHeight = child.getMeasuredHeight(); final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); int gravity = lp.gravity; if (gravity < 0) { gravity = minorGravity; } final int layoutDirection = getLayoutDirection(); final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection); switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { case Gravity.CENTER_HORIZONTAL: childLeft = paddingLeft + ((childSpace - childWidth) / 2) + lp.leftMargin - lp.rightMargin; break; case Gravity.RIGHT: childLeft = childRight - childWidth - lp.rightMargin; break; case Gravity.LEFT: default: childLeft = paddingLeft + lp.leftMargin; break; } if (hasDividerBeforeChildAt(i)) { childTop += mDividerHeight; } childTop += lp.topMargin; setChildFrame(child, childLeft, childTop + getLocationOffset(child), childWidth, childHeight); childTop += childHeight + lp.bottomMargin + getNextLocationOffset(child); i += getChildrenSkipCount(child, i); } } } private void setChildFrame(View child, int left, int top, int width, int height) { child.layout(left, top, left + width, top + height); }
/* * Draw traversal performs several drawing steps which must be executed * in the appropriate order: * * 1. Draw the background * 2. If necessary, save the canvas' layers to prepare for fading * 3. Draw view's content * 4. Draw children * 5. If necessary, draw the fading edges and restore layers * 6. Draw decorations (scrollbars for instance) */