view的onMeasure()方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//如果父控件指定了大小(mode为exacty或者at_most),将其设置为父控件指定的值,否则设置为该控件最小宽度(通过minWidth及minHeight指定或者根据背景图片指定),其中用到的两个函数见下
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
//获取控件最小宽高
protected int getSuggestedMinimumWidth() {
return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
}
//上面的getDefaultSize方法源码,很简单,一目了然。
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
//该函数最关键,决定着view的measuredWidth和measuredHeight,我们重写onMeasure时一般调用该函数设置view宽度,两个参数是纯size,不包括mode的
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
//这不知道是在做什么的
boolean optical = isLayoutModeOptical(this);
if (optical != isLayoutModeOptical(mParent)) {
Insets insets = getOpticalInsets();
int opticalWidth = insets.left + insets.right;
int opticalHeight = insets.top + insets.bottom;
measuredWidth += optical ? opticalWidth : -opticalWidth;
measuredHeight += optical ? opticalHeight : -opticalHeight;
}
setMeasuredDimensionRaw(measuredWidth, measuredHeight);
}
// 貌似这个才是决定性函数
private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
mMeasuredWidth = measuredWidth;
mMeasuredHeight = measuredHeight;
mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
}