當(dāng) Activity 獲取到焦點(diǎn)后牧愁,將會(huì)請(qǐng)求繪制它的布局。Android 框架負(fù)責(zé)處理繪制流程外莲,而且該 Activity 必須提供它布局層次的根節(jié)點(diǎn)猪半。
繪制從布局的根節(jié)點(diǎn)開始,它會(huì)請(qǐng)求測(cè)量和繪制布局樹。通過(guò)遍歷布局樹并渲染每個(gè)在有效區(qū)域內(nèi)的視圖來(lái)處理繪圖磨确。ViewGroup 負(fù)責(zé)依次請(qǐng)求每個(gè)子視圖去繪制(調(diào)用 draw() 方法)沽甥,View 負(fù)責(zé)繪制它自己。因?yàn)槭前错樞虮闅v樹俐填,意味著父視圖會(huì)在子視圖之前被繪制安接,同級(jí)視圖會(huì)按被添加到樹的順序依次繪制。
繪制布局之前先經(jīng)過(guò)兩個(gè)過(guò)程:measure(測(cè)量) 和 layout(布局)英融。測(cè)量過(guò)程在 View 的 measure(int, int)
中實(shí)現(xiàn)盏檐,并且是根據(jù)視圖樹自上而下的遍歷。在遞歸過(guò)程驶悟,每個(gè) View 會(huì)它的尺寸規(guī)格沿樹向下傳遞胡野。測(cè)量結(jié)束時(shí),每個(gè)視圖已經(jīng)保存了自己的測(cè)量值痕鳍。第二個(gè)過(guò)程發(fā)生在 layout(int, int, int, int)
硫豆,也是由上而下的。在這個(gè)過(guò)程笼呆,父視圖的負(fù)責(zé)根據(jù)測(cè)量過(guò)程計(jì)算的結(jié)果來(lái)放置它的子視圖熊响。
框架不會(huì)繪制在無(wú)效區(qū)域的 View 對(duì)象,以及 View 的背景诗赌。你可以通過(guò)調(diào)用 invalidate()方法強(qiáng)制 View 繪制汗茄。
當(dāng) View 對(duì)象的 measure()方法返回時(shí),它的 getMeasuredWidth()和 getMeasuredHeight()方法肯定是可以獲取到有效值的铭若,以及該 View 對(duì)象下的子 View 也一樣洪碳。View 對(duì)象測(cè)量的寬高會(huì)受父節(jié)點(diǎn)的約束。這保證在測(cè)量過(guò)程結(jié)束時(shí)叼屠,所有父視圖都能接受它們子視圖的測(cè)量值瞳腌。父視圖可能會(huì)調(diào)用子視圖的 measure(int,int)方法一次以上。例如镜雨,父視圖可以在不指定尺寸情況下先測(cè)量每個(gè)子視圖想要多大尺寸嫂侍,如果所有子視圖測(cè)量值的和太大或太小,那么父視圖會(huì)用精確數(shù)值再次調(diào)用 measure()(也就是說(shuō)荚坞,如果子視圖對(duì)它們獲得的尺寸不滿意挑宠,那么父視圖將會(huì)干涉并根據(jù)情況設(shè)置第二種測(cè)量規(guī)則)。
調(diào)用 requestLayout()方法會(huì)觸發(fā) View 的 layout 流程西剥。這個(gè)方法通常由 View 自己調(diào)用痹栖,當(dāng)它認(rèn)為當(dāng)前布局需要重新調(diào)整的時(shí)候亿汞。
測(cè)量過(guò)程使用兩個(gè)類來(lái)傳遞尺寸瞭空。View 對(duì)象使用 ViewGroup.LayoutParams類告訴父視圖它們想如何被測(cè)量和放置。基本的 ViewGroup.LayoutParams類描述了 View 想要多大的寬和高咆畏。它可以指定為以下其中之一:
- 精確的數(shù)字
- MATCH_PARENT南捂,意思是這個(gè) View 需要和它父視圖一樣大(減去padding)
- WRAP_CONTENT,意思是這個(gè) View 需要足夠包裹內(nèi)容的尺寸(加上padding)
ViewGroup的不同子類也分別有各自的 ViewGroup.LayoutParams子類,如FrameLayout.LayoutParams,GridLayout.LayoutParams,LinearLayout.LayoutParams,LinearLayoutCompat.LayoutParams,RecyclerView.LayoutParams,RelativeLayout.LayoutParams旧找。例如溺健, RelativeLayout有它自己的 ViewGroup.LayoutParams子類,包含讓子 View 水平居中和垂直居中的能力钮蛛。
MeasureSpec對(duì)象用于將尺寸規(guī)格從父視圖沿樹向下傳遞到子視圖鞭缭。它可以是是以下三種模式之一:
UNSPECIFIED: 未指定尺寸,這是父節(jié)點(diǎn)用于確定子視圖所需尺寸魏颓。例如岭辣,一個(gè) LinearLayout
可以調(diào)用它子視圖的 measure(int widthMeasureSpec, int heightMeasureSpec)方法,并設(shè)置 heightMeasureSpec
為 UNSPECIFIED甸饱, widthMeasureSpec為 EXACTLY + 240沦童,計(jì)算出當(dāng)寬為 240 像素時(shí)該子視圖需要多高。EXACTLY: 為子視圖指定一個(gè)確切的尺寸叹话。子視圖必須使用這個(gè)尺寸偷遗,并確保所有子視圖在這個(gè)尺寸之內(nèi)。
AT MOST: 為子視圖指定一個(gè)最大尺寸驼壶。子視圖必須確保它和它的所有子視圖在這個(gè)尺寸之內(nèi)氏豌。