在一段無法下載下傳的中文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;
}