void layoutVertical(int left, int top, int right, int bottom) {
final int paddingLeft = mPaddingLeft;
int childTop;
int childLeft;
// Where right end of child should go
// LinearLayout可用的宽度
final int width = right - left;
// child最多能够到达的右边位置
int childRight = width - mPaddingRight;
// Space available for child
// 计算child的实际可用空间
int childSpace = width - paddingLeft - mPaddingRight;
// 计算子view的个数
final int count = getVirtualChildCount();
final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
final int minorGravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;
// 首先根据gravity的值计算出child的top值
switch (majorGravity) {
case Gravity.BOTTOM:
// mTotalLength contains the padding already
childTop = mPaddingTop + bottom - top - mTotalLength;
break;
// mTotalLength contains the padding already
case Gravity.CENTER_VERTICAL:
childTop = mPaddingTop + (bottom - top - mTotalLength) / 2;
break;
case Gravity.TOP:
default:
childTop = mPaddingTop;
break;
}
// 然后进行遍历,根据child的水平布局方式(水平居中、靠左或靠右)计算出child的left值
for (int i = 0; i < count; i++) {
final View child = getVirtualChildAt(i);
if (child == null) {
childTop += measureNullChild(i);
} else if (child.getVisibility() != GONE) {
// child的宽度和高度已经在measure步骤中计算过了,现在直接获取
final int childWidth = child.getMeasuredWidth();
final int childHeight = child.getMeasuredHeight();
// 获取child的布局参数
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;
// 计算完child的top和left值,获取到measure步骤中计算的宽和长,再调用setChildFrame方法设置child的位置
setChildFrame(child, childLeft, childTop + getLocationOffset(child), childWidth, childHeight);
private void setChildFrame(View child, int left, int top, int width, int height) {
// setChildFrame方法中调用的就是layout方法
child.layout(left, top, left + width, top + height);
}
childTop += childHeight + lp.bottomMargin + getNextLocationOffset(child);
i += getChildrenSkipCount(child, i);
}
}
}