啥都不说,先上源代码
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
//这在官方的文档中有说明,让我们当重写这个方法时,必须调用,不然会报非法异常
}
底层调用了setMeasuredDimention传入默认的大小,参数为getSuggestedMinimunWidth()的返回值,那么getSuggestedMinimunWidth()做了什么,我们看看
protected int getSuggestedMinimumWidth() {
return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
//这里的mBackground是Drawable对象
}
返回的背景图片的最小值与视图的最小值的最大值。
何以证明?
那么我们就查看一下mBackGround的由来。我查看了setBackgroundColor
setBackgroundResource的源代码,发现最终都是调用了setBackground。而setBackground又在底层调用了setBackgroundDrawable()方法
我就在这里找了一下,果不其然,被我发现了
if (mBackground == null
|| mBackground.getMinimumHeight() != background.getMinimumHeight()
|| mBackground.getMinimumWidth() != background.getMinimumWidth()) {
requestLayout = true;
}
// Set mBackground before we set this as the callback and start making other
// background drawable state change calls. In particular, the setVisible call below
// can result in drawables attempting to start animations or otherwise invalidate,
// which requires the view set as the callback (us) to recognize the drawable as
// belonging to it as per verifyDrawable.
mBackground = background;
if (background.isStateful()) {
background.setState(getDrawableState());
}
if (isAttachedToWindow()) {
background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false);
}
上面明显有一个赋值过程,当然这都不是重点。有兴趣可以去看看。
那么返回来我们看看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;
}
我们发现当Measure.mode==UNSPECIFIED,也即是不限制子视图的大小的时候,getDefault将返回背景图片的最小值与视图的最小值的最大值。当然在一般情况下,就是MeasureSpec.getSize的大小。
进一步,我们里来到了setMeasuredDmention()并将解析到的数据传入。
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);
}
我们发现在这里,这是对值进行了处理,
之后就传给了setMeasuredDimentionRaw(),那么在setMeasuredDimentionRaw又做了什么?,我们瞧瞧看。
private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
mMeasuredWidth = measuredWidth;
mMeasuredHeight = measuredHeight;
mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
}
将值传递给了View的测量宽度。那么我们就要想,之前使用getMeasureWidth()和getMeasureHeight()是不是传递的就是这个值呢?
我们看看去.
public final int getMeasuredWidth() {
return mMeasuredWidth & MEASURED_SIZE_MASK;
}
这是宽度的返回值。到这里你可能认为我真的去算!!!!!!我只能说你想多了
亏自己还是写程序的,自己测一下就是喽
public void getAnd(){
int a=400;
System.out.println(a&0x00ffffff);
}
带了个值试了一下,结果还是原来的数据看来自己猜的是对的。
也就是说我们通过setMesureDimention(int,int)来设置的值就是我们通过getMeasureWidth()和getMeasureHeight(int,int)设置的值。