// 所以,getChildMeasureSpec 这种方法的作用。就是依据
// 1、父视图 MyCustomLinearLayoutA 的 MeasureSpec
// 2、 除 MyCustomTextViewA
的本身尺寸之外 全部空间的总和
// 3、MyCustomTextViewA 本身的尺寸
// 这三个方面共同来计算出 MyCustomTextViewA
的 MeasureSpec
// 来看详细的逻辑:
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
// 得到父视图的mode和size
int specMode = MeasureSpec.getMode(spec);
int specSize = MeasureSpec.getSize(spec);
int size = Math.max(0, specSize - padding);
int resultSize = 0;
int resultMode = 0;
switch (specMode) {
// Parent has imposed an exact size on us
// 因为本demo中。MyCustomTextViewA 父视图的 specMode 为 EXACTLY。所以,仅仅看一条case语句了:
case MeasureSpec.EXACTLY:
// 在case语句中推断完父视图MyCustomLinearLayoutA 的mode之后,再来推断MyCustomTextViewA 的尺寸
// 也就是上文通过布局參数拿到的 我们在布局文件中写的宽和高的值
if (childDimension >= 0) {
// 假设我们在布局文件里为 MyCustomTextViewA 设置了详细的宽和高的值。那么将会用这个详细的值和EXACTLY
// 组合成一个MeasureSpec并返回
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size. So be it.
// 假设我们在布局文件里为 MyCustomTextViewA 设置的宽和高是MATCH_PARENT。那么将会用上文计算出的
// 可用空间(在本demo中为父视图的宽度和高度)和 EXACTLY 组合成一个MeasureSpec并返回
resultSize = size;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can‘t be
// 假设我们在布局文件里为 MyCustomTextViewA 设置的宽和高是WRAP_CONTENT。那么将会用上文计算出的
// 可用空间(在本demo中为父视图的宽度和高度)和 AT_MOST组合成一个MeasureSpec并返回
// bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
// 通过以上分析,MyCustomTextViewA 的onMeasure方法接收的參数相应的size不一定是其父视图的宽高
// 能够在布局文件里。将MyCustomTextViewA 的layout_width
改为"wrap_content"或详细的一个dp值
// 再复写MyCustomTextViewA 的onMeasure方法,进行验证
break;
}
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
}