天天看點

view onMeasure方法說明

 在一段無法下載下傳的中文API中對此函數有這樣的描述:

    //----------------------------------------------------------------

    protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec);

    View調用此方法來确定本身和所包含内容的大小。此方法被measure(int,int)喚起,而且必須被子類重寫以得到所包含内容的确切大小。

    注意:當重寫此方法時,必須調用setMeasureDimension(int,int)來儲存View的大小。如果沒有做到,将會引發一個measure(int,int)抛出的IllegalStateException(非法狀态錯誤)。超類onMeasure(int,int)可以被調用。

    編寫基類的确認大小的方法,預設情況下是根據其背景大小來确認,除非MeasureSepc允許有更大的高度或寬度。子類必須重寫onMeasure(int,int)以得到對其内容大小的更準确的測量。

    若此方法被重寫,它的子類需要確定其高度和寬度至少達到View所規定的最小值

   (可通過getSuggestedMinimumHeight()和getSuggestedMinimumWidth()得到)。

參數

        widthMeaureSpec           受上一層大小影響下的對水準空間的要求。可參看View.MeasureSpec。

        heightMeasureSpec         受上一層大小影響下的對垂直空間的要求。可參看View.MeasureSpec。

除非你總是需要一個100×100像素的控件,否則,你必須要重寫onMeasure。

onMeasure方法在控件的父元素正要放置它的子控件時調用。它會問一個問題,“你想要用多大地方啊?”,然後傳入兩個參數——widthMeasureSpec和heightMeasureSpec。

它們指明控件可獲得的空間以及關于這個空間描述的中繼資料。

 比傳回一個結果要好的方法是你傳遞View的高度和寬度到setMeasuredDimension方法裡。

接下來的代碼片段給出了如何重寫onMeasure。注意,調用的本地空方法是來計算高度和寬度的。它們會譯解widthHeightSpec和heightMeasureSpec值,并計算出合适的高度和寬度值。

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int measuredHeight = measureHeight(heightMeasureSpec);

int measuredWidth = measureWidth(widthMeasureSpec);

setMeasuredDimension(measuredHeight, measuredWidth);

}

private int measureHeight(int measureSpec) {

// Return measured widget height.

}

private int measureWidth(int measureSpec) {

// Return measured widget width.

}

邊界參數——widthMeasureSpec和heightMeasureSpec ,效率的原因以整數的方式傳入。在它們使用之前,首先要做的是使用MeasureSpec類的靜态方法getMode和getSize來譯解,如下面的片段所示:

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

依據specMode的值,如果是AT_MOST,specSize 代表的是最大可獲得的空間;如果是EXACTLY,specSize 代表的是精确的尺寸;如果是UNSPECIFIED,對于控件尺寸來說,沒有任何參考意義。

當以EXACT方式标記測量尺寸,父元素會堅持在一個指定的精确尺寸區域放置View。在父元素問子元素要多大空間時,AT_MOST訓示者會說給我最大的範圍。在很多情況下,你得到的值都是相同的。

在兩種情況下,你必須絕對的處理這些限制。在一些情況下,它可能會傳回超出這些限制的尺寸,在這種情況下,你可以讓父元素選擇如何對待超出的View,使用裁剪還是滾動等技術。

 接下來的架構代碼給出了處理View測量的典型實作:

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

int measuredHeight = measureHeight(heightMeasureSpec);

int measuredWidth = measureWidth(widthMeasureSpec);

setMeasuredDimension(measuredHeight, measuredWidth);

}

private int measureHeight(int measureSpec) {

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

// Default size if no limits are specified.

int result = 500;

if (specMode == MeasureSpec.AT_MOST) 

{

// Calculate the ideal size of your

// control within this maximum size.

// If your control fills the available

// space return the outer bound.

result = specSize;

else if (specMode == MeasureSpec.EXACTLY) 

{

// If your control can fit within these bounds return that value.

result = specSize;

}

return result;

}

private int measureWidth(int measureSpec) {

int specMode = MeasureSpec.getMode(measureSpec);

int specSize = MeasureSpec.getSize(measureSpec);

// Default size if no limits are specified.

int result = 500;

if (specMode == MeasureSpec.AT_MOST)

{

// Calculate the ideal size of your control

// within this maximum size.

// If your control fills the available space

// return the outer bound.

result = specSize;

else if (specMode == MeasureSpec.EXACTLY) 

{

// If your control can fit within these bounds return that value.

result = specSize;

}

return result;

}