在當一個活動接收到焦點時,將被要求繪制它的布局。
Android框架將處理這個繪畫的過程,但是活動必須提供它的布局層次的根節點。
繪畫從布局的根節點開始。
它被要求來測量和繪制布局樹。
繪畫通過遍歷布局樹並渲染每個和失效區域相交的視圖來處理。
相應的,每個視圖組負責請求繪制它的子視圖(通過draw() 方法)而每個視圖負責畫它自己。因為這個樹是順序遍歷的,這意味著先畫父節點(也就是在屏幕後面),然後按照樹中出現的順序畫其同層次節點。
框架將不會畫不在失效區域的視圖,而且還將會幫你畫視圖背景。
你可以強制一個視圖被重畫,通過調用invalidate()。
繪畫布局共有兩步:一個度量過程和一個布局過程。
度量過程在measure(int, int)裡實現且是一個自頂向下的視圖樹遍歷。
每個視圖在遞歸時往下推送尺寸規格。
在度量過程的最後,每個視圖都已經保存了自己的度量。
第二個過程發生在layout(int, int, int, int) 中並且也是自頂向下。
在這個過程中,每個父節點負責定位它的所有子節點,通過使用在度量過程中計算得到的尺寸。
當一個視圖的measure()方法返回時,它的getMeasuredWidth()和getMeasuredHeight() 值必須被設置,以及所有這個視圖子節點的值。一個視圖的度量的寬度和高度值必須符合父視圖引入的限制。這確保在度量過程之後,所有父節點接受所有它們的子節點的度量值。
一個父視圖可能會在其子視圖上多次調用measure()方法。
比如,父視圖可能會通過未指定的尺寸調用measure來發現它們的大小,然後使用實際數值再次調用measure(),如果所有子視圖未做限制的尺寸總合過大或過小(也即是,如果子視圖之間不能對各自占據的空間達成共識的話,父視圖將會干預並設置第二個過程的規則)。
要開始一個布局,可調用requestLayout()。這個方法通常在視圖認為它自己不再適合它當前的邊界的情況下被調用。
度量過程使用兩個類來交流尺寸。
View.MeasureSpec類被視圖用來告訴它們的父視圖它們想如何被度量和定位。
基礎的LayoutParams類僅僅描述了視圖想有多大(高和寬)。
對於每個維度,它可以指定下面之一:
· 一個准確的數值 www.2cto.com
· FILL_PARENT, 這意味著視圖想和父視圖一樣大(減掉填充padding)。
· WRAP_CONTENT, 這意味著視圖只想有剛好包裝其內容那麼大(加上填充)
對於不同的ViewGroup子類,有相應的LayoutParams子類。
比如,相對布局RelativeLayout有它自己的LayoutParams子類,這包含了能夠讓子視圖橫向和豎向居中顯示的能力。
度量規格(MeasureSpecs)被用來沿著樹從父到子的下傳度量需求。
一個MeasureSpecs可以是下面三種模式之一:
· UNSPECIFIED: 這被父視圖用來決定其子視圖期望的尺寸。
比如,一個線性布局可能在它的子視圖上調用measure() on its child,通過設置其高度為UNSPECIFIED 以及一個寬度為EXACTLY 240,來找出這個子視圖在給定240像素寬度的情況下需要顯示多高。
· EXACTLY: 這被父視圖用來給子視圖強加一個准確的尺寸。子視圖必須使用這個大小,並確保其所有的後代將適合這個尺寸。
· AT_MOST: 這被父視圖用來給子視圖強加一個最大尺寸。子視圖必須確保它自己以及所有的後代都適合這個尺寸。