ViewRoot和DecorView
ViewRoot對應(yīng)于ViewRootImpl類筋现,它是連接WindowManager和DecorView的紐帶,View的三大流程均是通ViewRoot來完成的晦款,在ActivityThread中,當Activity對象被創(chuàng)建完畢后枚冗,會講DecorView添加到Window中缓溅,同時會創(chuàng)建ViewRootImpl對講,通過ViewRootImpl.setView方法將ViewRootImpl和DecorView關(guān)聯(lián)赁温。
View的繪制流程是從ViewRoot的performTraversals方法開始的坛怪,它經(jīng)過measure,layout股囊,draw三個過程袜匿,其中measure用來測量View的寬高,layout用來確定View在父容器中的放置位置毁涉,draw則負責將view繪制在屏幕上沉帮。
performTraversals會依次調(diào)用performMeasure、performLayout贫堰、performDraw三個方法穆壕,這三個方法分別完成頂級View的measure、layout其屏、draw這三個過程喇勋,其中在performMeasure中會調(diào)用measure方法,在measure方法中又會調(diào)用onMeasure方法偎行,在onMeasure方法中則會對所有子元素進行measure過程川背,這個時候measure流程就從父容器傳遞到子元素了,這樣就完成了一次measure過程蛤袒。接著子元素會重復(fù)父容器的measure過程熄云,如此反復(fù)就完成了整個view樹的遍歷,performLayout妙真、performDraw傳遞流程和performMeasure是類似的缴允,唯一不同的是performDraw的傳遞過程是在draw方法中通過dispatchDraw來實現(xiàn)的,不過這本質(zhì)沒有區(qū)別珍德。
measure過程:
如果只是一個原始的View练般,那么通過measure->onMeasure方法就可以完成測量過程,如果是一個ViewGroup锈候,除了完成自己的測量外薄料,還會遍歷去調(diào)用所有子元素的measure方法,各個子元素再遞歸調(diào)用這個過程
直接繼承View的自定義控件需要重寫onMeasure方法并且設(shè)置wrap_content時的自身大小泵琳,否在在布局中使用wrap_content就相當于使用match_partent
因為默認寬高等于specSize摄职,這種情況下specSize是partentSize誊役,也就是父容器目前可用大小
layout過程:
layout的作用是ViewGroup用來確定子元素的位置,當ViewGroup的位置被確定后谷市,他在onLayout中會遍歷所有的子元素并調(diào)用其layout方法势木,在layout方法中onLayout又會被調(diào)用。layout方法確定view本身的位置歌懒,onlayout方法確定所有子元素的位置
draw過程:
- 繪制背景background.draw(canvas)
- 繪制自己(onDraw)
- 繪制children(dispatchDraw)
- 繪制裝飾(onDrawForeground)
-
繪制默認焦點突出顯示(drawDefaultFocusHighlight(canvas))
image.png