當一個activity獲得焦點時, 它會被要求繪製它的布局. Android架構將處理繪製的過程, 但是activity必須提供它的布局體系的根節點. 繪製將從根節點開始, 根節點被要求測量和繪製布局樹. 繪製是通過遍曆樹並渲染每個處於有效地區內的view來完成的. 每個view group依次負責要求它的每個子項目繪製自身,而每個view負責繪製它自己. 由於樹使用中序遍曆(in-order traverse), 這意味著父元素首先被繪製, 然後是子項目按照它們出現的順序來繪製. (譯者注: 這裡in-order疑為pre-order)
android架構不會繪製處於無效地區中的view, 並且會幫你繪製背景view.
你可以調用invalidate()方法來強制一個view重新繪製.
繪製布局是一個兩次的過程: 一個測量過程和一個版面配置階段. 測量過程實現在measure(int,int)中, 是對View樹的一個自頂向下的遍曆. 每個View將尺寸要求向下一層傳遞. 在測量過程的最後, 每個view儲存了它的測量值. 第二個過程在layour(int,int,int,int)中發生, 同樣從上到下. 在這一個過程中每個父元素負責根據在測量過程中計算的大小, 將子項目放在合適的位置.
當一個View的measure()方法返回時, 它和它的後代元素的getMeasuredWidth()和getMeasuredHeight()值必須被設定. 一個view的測量寬度和測量高度必須遵循它的父View的限制. 這將保證在測量過程之後, 所有的父元素接受它們的子項目的測量值. 一個父View可能對它的子項目不止調用一次measure(). 例如, 父元素可能不帶參數的測量每個子項目一次來得到它們希望的大小,
然後再次調用帶參數的measure()如果子項目的大小超過限制. (即, 如果子項目相互無法協調, 父元素將為它們設定規則.)
使用requestLayout()來初始化一個布局. 該方法一般由一個View對自身調用, 當它認為它無法置於它當前的限制地區內時.
測量過程使用兩個類來傳遞尺寸. View使用View.MeasureSpec來告訴它們的父元素它們希望如何被測量和放置. LayoutParams類描述了一個View希望它的長和寬各為多少. 它可以指定下列的一個:
- 一個確定的數值
- 表示View希望和它的父元素一樣大(除去padding)
- 表示View希望能足夠包括它的內容(加上padding)
LayoutParams 的不同子類可用於不同的ViewGroup子類. 例如RelativeLayout 有它自己的LayoutParams子類, 該子類包括了讓每個子View水平和豎直置中的功能.
MeasureSpecs 可用來將要求向下傳遞. 一個MeasureSpec 可以為三種模式中的一種:
- UNSPECIFIED: 一個父元素用它來決定子View的期望大小. 例如, 一個 LinearLayout 可能需要對它的子項目調用measure(), 將高度設為UNSPECIFIED ,寬度設為 EXACTLY 240來得到子View在寬度為240像素時,它的期望高度是多少.
- EXACTLY: 一個父元素用它來為子項目強加一個精確的大小. 子項目必須使用這個大小, 並保證它的所有後代元素遵守這個限制.
- AT_MOST: 父元素用它來為子項目強加一個最大尺寸. 子項目必須保證它和它所有的後代在這個大小之內