ViewRoot和DecorView
ViewRoot對應(yīng)于ViewRootImpl類,它是連接WindowManager和DecorView的紐帶,View的三大流程均是通ViewRoot來完成的,在ActivityThread中,當(dāng)Activity對象被創(chuàng)建完畢后,會(huì)講DecorView添加到Window中,同時(shí)會(huì)創(chuàng)建ViewRootImpl對講,通過ViewRootImpl.setView方法將ViewRootImpl和DecorView關(guān)聯(lián)。
View的繪制流程是從ViewRoot的performTraversals方法開始的,它經(jīng)過measure,layout,draw三個(gè)過程,其中measure用來測量View的寬高,layout用來確定View在父容器中的放置位置,draw則負(fù)責(zé)將view繪制在屏幕上。
performTraversals會(huì)依次調(diào)用performMeasure、performLayout、performDraw三個(gè)方法,這三個(gè)方法分別完成頂級View的measure、layout、draw這三個(gè)過程,其中在performMeasure中會(huì)調(diào)用measure方法,在measure方法中又會(huì)調(diào)用onMeasure方法,在onMeasure方法中則會(huì)對所有子元素進(jìn)行measure過程,這個(gè)時(shí)候measure流程就從父容器傳遞到子元素了,這樣就完成了一次measure過程。接著子元素會(huì)重復(fù)父容器的measure過程,如此反復(fù)就完成了整個(gè)view樹的遍歷,performLayout、performDraw傳遞流程和performMeasure是類似的,唯一不同的是performDraw的傳遞過程是在draw方法中通過dispatchDraw來實(shí)現(xiàn)的,不過這本質(zhì)沒有區(qū)別。
measure過程:
如果只是一個(gè)原始的View,那么通過measure->onMeasure方法就可以完成測量過程,如果是一個(gè)ViewGroup,除了完成自己的測量外,還會(huì)遍歷去調(diào)用所有子元素的measure方法,各個(gè)子元素再遞歸調(diào)用這個(gè)過程
直接繼承View的自定義控件需要重寫onMeasure方法并且設(shè)置wrap_content時(shí)的自身大小,否在在布局中使用wrap_content就相當(dāng)于使用match_partent

因?yàn)槟J(rèn)寬高等于specSize,這種情況下specSize是partentSize,也就是父容器目前可用大小
layout過程:
layout的作用是ViewGroup用來確定子元素的位置,當(dāng)ViewGroup的位置被確定后,他在onLayout中會(huì)遍歷所有的子元素并調(diào)用其layout方法,在layout方法中onLayout又會(huì)被調(diào)用。layout方法確定view本身的位置,onlayout方法確定所有子元素的位置
draw過程:
- 繪制背景background.draw(canvas)
- 繪制自己(onDraw)
- 繪制children(dispatchDraw)
- 繪制裝飾(onDrawForeground)
-
繪制默認(rèn)焦點(diǎn)突出顯示(drawDefaultFocusHighlight(canvas))
image.png
