View的工作原理

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

image.png

因?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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容