啥都不說,先上源代碼
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=;
System.out.println(a&);
}
帶了個值試了一下,結果還是原來的資料看來自己猜的是對的。
也就是說我們通過setMesureDimention(int,int)來設定的值就是我們通過getMeasureWidth()和getMeasureHeight(int,int)設定的值。