onMeasure()
是您有機會告訴Android您希望自定義視圖的大小取決於父級提供的佈局約束;這也是您的自定義視圖的機會,可以瞭解這些佈局約束條件(如果您希望在match_parent
情況下的行爲與wrap_content
情況下的行爲不同)。這些約束被打包到傳入該方法的MeasureSpec
值中。下面是模式值的粗略的相關性:
- EXACTLY指
layout_width
或layout_height
值設定爲特定值。你可能應該讓你的觀點大小。當使用match_parent
時,也可以觸發這種情況,以將尺寸精確地設置爲父視圖(這與框架中的佈局相關)。
- AT_MOST通常表示
layout_width
或layout_height
值設定爲match_parent
wrap_content
或其中需要的最大尺寸(這是佈局依賴於框架),並且父維度的大小的值。你不應該大於這個尺寸。
- 未知通常表示
layout_width
或layout_height
值設置爲wrap_content
,沒有任何限制。你可以是任何你想要的大小。某些佈局還會使用此回調來確定您希望的尺寸,然後再決定在第二個度量請求中實際再次傳遞給您的參數。
與onMeasure()
存在的契約是:setMeasuredDimension()
MUST在與大小結束時調用你想的觀點是。此方法由所有框架實現調用,包括在View
中找到的默認實現,因此,如果符合您的用例,則可以安全地調用super
來代替。因爲該框架確實應用了默認實現,所以您可能不需要重寫此方法,但如果視圖空間小於內容(如果不存在),並且如果視圖空間小於內容你在兩個方向上用wrap_content
佈局你的自定義視圖,你的視圖可能根本不顯示,因爲框架不知道它有多大!
一般來說,如果要覆蓋View
而不是另一個現有的小工具,它可能是一個好主意,提供一個實現,即使是這樣的簡單:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = 100;
int desiredHeight = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}
希望幫助。
嘿@Devunwired很好的解釋迄今爲止我讀的最好的。你的解釋回答了我的許多問題,並清除了一些疑問,但仍有一個問題仍然存在:如果我的自定義視圖位於ViewGroup中,並且其他視圖(無論哪種類型)ViewGroup將其所有子項爲每個探測器的LayoutParams約束,並要求每個孩子根據自己的約束來自我測量? – pharaoh
是的,這就是'ViewGroup'的'measureChildren()'方法在度量/佈局過程中所做的。 – Devunwired
請注意,如果您重寫任何ViewGroup子類的onMeasure,則此代碼不會執行此操作。你的子視圖不會顯示出來,全部大小都爲0x0。如果您需要重寫自定義ViewGroup的onMeasure,請更改widthMode,widthSize,heightMode和heightSize,然後使用MeasureSpec.makeMeasureSpec將它們編譯回measureSpecs,並將生成的整數傳遞給super.onMeasure。 – Alexey