View的繪制流程:OnMeasure()——>OnLayout()——>OnDraw()
View的繪制過程就是從ViewRoot的performTraversals方法開始的,它經(jīng)過measure、layout、draw三個(gè)過程才能最終將一個(gè)View繪制出來:
1.measure用來測量View的寬和高。
2.layout用來確定View在父容器中放置的位置。
3.draw用來將view繪制在屏幕上。
大致的流程如下圖所示:

如圖所示,performTraversals會(huì)依次調(diào)用performMeasure、performLayout和performDraw三個(gè)方法,這三個(gè)方法分別完成頂級View的measure、layout、draw這個(gè)三個(gè)流程。其中:
1.perfromMeasure中會(huì)調(diào)用measure方法,在measure方法中又會(huì)調(diào)用onMeasure方法,在onMeasure方法中會(huì)對所有的子元素進(jìn)行measure過程,這個(gè)時(shí)候measure流程就從父容器傳遞到子元素中了,這樣就完成了一次measure過程。接著子元素會(huì)重復(fù)父元素的measure過程,如此反復(fù)就完成整個(gè)View樹的遍歷。
view的繪制流程是自上而下再自下而上的流程。父元素將自身的size長寬度和測量模式傳遞給子view,子view根據(jù)父元素確定自身的size長寬度和測試模式。接著子元素又將自身的長寬度和測量模式傳遞給子view,如此反復(fù)就完成整個(gè)View樹的遍歷。如果父元素是固定的size或match_parent,那么子元素隨即可以確定size(長度和寬度)和測量模式為Exactly。如果父元素是wrap_content,那么就要根據(jù)子元素的size返回給父元素,父元素才能確定自身的size。
2.performLayout的傳遞流程和performMeasure是一樣的。
3.performDraw的傳遞過程是在draw方法中通過dispathDraw來實(shí)現(xiàn)的,本質(zhì)上并沒有區(qū)別。
二、自定義view中重寫的onMeasure方法為何只有兩個(gè)參數(shù),而不是四個(gè)參數(shù)(長度、寬度、長度測量模式、寬度測量模式)?
因?yàn)閰?shù)太多會(huì)占用內(nèi)存。
所以這兩個(gè)參數(shù)并不是實(shí)際的長度和寬度。而是長度和測試模式的拼接。java 中 int 類型數(shù)據(jù)占用 32 位,包括符號位和幅度位。這里的參數(shù)就是最高兩位是測量模式(00、01、11代表三種測量模式),剩下30位存放實(shí)際的長度或?qū)挾取?/p>
三、Mea和sureSpec
MeasureSpec的中文意思是測量規(guī)格的意思,MeasureSpec代表一個(gè)32的int值,高2位代表SpecMode測量模式,低30位代表SpecSize測量規(guī)格大小。
經(jīng)常使用的三個(gè)函數(shù):
1、public static int makeMeasureSpec(int size,int mode)? ?// 構(gòu)造一個(gè)MeasureSpec
2、public static int getMode(int measureSpec)? ? ? ? // 獲取MeasureSpec的測量模式
3、public static int getSize(int measureSpec)? ? ? ? ? // 獲取MeasureSpec的測量大小
SpecMode分為三類,每一類都沒有他們對應(yīng)的約束。
1、UNSPECIFIED
父容器不對View有任何限制,要多大就給多大,這種情況,一般我們自定義View用不到。
2、Exactly
這個(gè)表示準(zhǔn)確值,這個(gè)對應(yīng)著LayoutParams中的matchparent和準(zhǔn)確值,這個(gè)時(shí)候View的最終大小就是SpecSize所指定的數(shù)。
3、AT_MOST
父容器指定了一個(gè)可用大小即SpecSize,View的大小不能大于該值,具體是什么要看View中自己的處理,所有自定義View時(shí),我們需要自己在measure里面處理設(shè)置布局的大小,它對應(yīng)layoutparams中的wrap_content
四、View的繪制流程是從Activity的哪個(gè)生命周期方法開始執(zhí)行的
onResume方法執(zhí)行之后開始。