當 Activity
收到焦點時,系統會要求繪製版面配置。Android 架構會處理繪圖的程序,但 Activity
必須提供其版面配置階層的根節點。
繪圖會從版面配置的根節點開始。要求測量並繪製版面配置樹狀結構。系統會追蹤樹狀結構並算繪每個與無效區域相交的 View
,藉此處理繪圖。因此,每個 ViewGroup
會負責要求繪製其各個子項 (使用 draw()
方法)。每個 View
會負責繪圖本身。由於樹狀結構預先進行遍歷,這意味著父項將被繪製其子項之前 (即之後),同層級則按照其在樹狀結構中出現的順序繪製。
注意:此架構不會繪製不在有效區域內的 View
物件,並且會為您繪製 View
背景。
您可以呼叫 invalidate()
來強制 View
進行繪圖。
繪製版面配置分為兩種程序:測量過程和版面配置過程。
測量過程
測量票證已實作 measure(int, int)
中,且位於 View
樹狀結構的上一層周遊。各個 View
會在遞迴期間將維度規格推送到樹狀結構中。測量過程結束時,每個 View
都會儲存測量結果。第二個過程是在 layout(int, int, int, int)
中進行,且為由上而下。在票證中,每個父項都必須使用測量票證計算的大小來指定所有子項。
當 View
物件的 measure()
方法回傳,getMeasuredWidth()
和 getMeasuredHeight()
值必須設定,以及所有 View
物件的子系。View
物件的測量寬度和測量高度值必須符合 View
物件父項所設的限制。此做法可確保在評估標準結束時,所有父項都必須接受子項的所有測量。父項 View
可以對其子項多次呼叫 measure()
。舉例來說,父項可以用未指定的維度測量每個子項一次,藉此判斷所需的維度,如果所有子項的未限制大小總和過大或過小 (亦即各個子項彼此不認同各自獲得的空間,父項就會攔截並在第二次過程時設定規則),則再次用實際數字對其呼叫 measure()
。
測量過程會透過兩個類別來傳送維度。View
物件會使用 ViewGroup.LayoutParams
類別,向父項說明評估方式和位置。基本 ViewGroup.LayoutParams
類別僅會說明 View
想要的寬度和高度的範圍。每個維度都可以指定下列其中一項:
- 實際數字
MATCH_PARENT
,這表示View
想要與父項一樣大 (減去邊框間距)WRAP_CONTENT
,這表示View
的大小必須夠高,才能納入其內容 (加上邊框間距)。
ViewGroup
的不同子類別有 ViewGroup.LayoutParams
的子類別。舉例來說,RelativeLayout
有專屬的 ViewGroup.LayoutParams
子類別,能夠水平和垂直將子項 View
物件置中。
MeasureSpec
物件的用途是將樹狀結構從父項向下推到子項。MeasureSpec
可為以下三種模式之一:
UNSPECIFIED
:父項會使用這個屬性來確定子項View
的所需維度。舉例來說,LinearLayout
可以在其子項上呼叫measure()
,高度設為UNSPECIFIED
,寬度為EXACTLY
240,以找出子項View
想要獲得 240 像素寬度的高度。EXACTLY
:父項會使用這個欄位為子項施加確切大小。子項必須使用這個尺寸,並保證所有子系都符合該尺寸規定。AT MOST
:父項會使用這個欄位為子項設定尺寸上限。子項必須保證其及其所有子系在這個尺寸內。
版面配置過程
如要啟動版面配置,請呼叫 requestLayout()
。當 View
認為其不再超出目前邊界時,就會自行呼叫這個方法。