/**
* 计算所有ChildView的宽度和高度,然后根据ChildView的计算结果,设置自己的宽和高
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
/**
* 获得此ViewGroup上级容器为其设置的宽和高,以及测量模式
*/
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
// 通过ViewGroup的measureChildren方法为其所有的childrenView设置宽和高
measureChildren(widthMeasureSpec, heightMeasureSpec);
/**
* 记录如果是wrap_content时,设置的宽和高
*/
int width = 0;
int height = 0;
int cCount = getChildCount();
int cWidth = 0;
int cHeight = 0;
MarginLayoutParams cParams = null;
// 用于计算左边两个childView的高度
int lHeight = 0;
// 用于计算右边两个childView的高度,最终高度取二者之间大值
int rHeight = 0;
// 用于计算上边两个childView以及设置的margin的所确定的宽度
int tWidth = 0;
// 用于计算下面两个childiew以及设置的margin的所确定的宽度,最终宽度取二者之间大值
int bWidth = 0;
/**
* 根据childView计算得出的宽和高,以及设置的margin计算容器的宽和高,主要用于容器是warp_content时
*/
for (int i = 0; i < cCount; i++) {
View childView = getChildAt(i);
cWidth = childView.getMeasuredWidth();
cHeight = childView.getMeasuredHeight();
cParams = (MarginLayoutParams) childView.getLayoutParams();
// 上面两个childView确定的宽度
if (i == 0 || i == 1) {
tWidth += cWidth + cParams.leftMargin + cParams.rightMargin;
}
// 下面两个childView确定的宽度
if (i == 2 || i == 3) {
bWidth += cWidth + cParams.leftMargin + cParams.rightMargin;
}
// 左边两个childView确定的高度
if (i == 0 || i == 2) {
lHeight += cHeight + cParams.topMargin + cParams.bottomMargin;
}
// 右边两个childView确定的高度
if (i == 1 || i == 3) {
rHeight += cHeight + cParams.topMargin + cParams.bottomMargin;
}
}
// 取最大值
width = Math.max(tWidth, bWidth);
height = Math.max(lHeight, rHeight);
/**
* 如果是精确值或match_parent,设置为父容器计算的值,否则设置为我们计算的值
*
*/
setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth
: width, (heightMode == MeasureSpec.EXACTLY) ? sizeHeight
: height);
}