當我們開始繪制一個View的時候,我們要先思考一下,系統繪制是如何繪制出這些View的,我們都知道,我們畫圖形,就必須知道圖形的位置和寬高大小,那么同樣,系統在繪制View前也需要對View進行測量,即告訴系統需要繪制多大的View,這就涉及到我們現在要用的一個方法onMeasure()
Android系統提供了一個類----MeasureSpec,通過它來測量View,測量的模式有三種:
EXACTLY:精確模式 當我們將寬度和高度設置成了match_parent或者給定了具體的數值之后,系統使用的是精確模式
AT_MOST:最大值模式 當我們將寬高設置了wrap_content時,控件大小隨著子控件或內容的大小變化而變化
UNSPECIFIED:不指定其大小測量模式,View想多大就多大,通常情況下在自定義View時才會使用
具體的看如下代碼:
AT_MOST = wrap_content
EXACTLY = match_parent
EXACTLY = 20dp;
首先我們先看看系統的onMeasure方法做了什么事吧
看到一個很有用的方法:setMeasuredDimension()
再看系統默認給我們的控件設置的大小吧
我們可以看到 使用MeasureSpec類去獲取控件的模式和大小
通過系統源碼得知 如果我們沒有設置控件大小 那么控件會在
AT_MOST和EXACTLY時占有父控件所有大小當指定了一個精確大小的時候 設置的值才會是我們設置的大小
看過上面源碼 相信大家看到了兩個很有用的方法:
int mode = MeasureSpec.getMode(heightMeasureSpec);
int size = MeasureSpec.getSize(heightMeasureSpec);
從MeasureSpec對象中獲取具體的測量模式和大小
然后通過判斷測量模式給出不同的測量值,當mode為EXACTLY時使用制定的size即可,當為其他兩種模式的時候需要給它一個默認值,如果指定warp_content屬性時,則需要取出我們指定的大小與size中最小的一個來作為測量值:
if (mode == MeasureSpec.EXACTLY) {
height = size;
} else {
height = 400;
if (mode == MeasureSpec.AT_MOST) {
height = Math.min(height, size);
}
}