【UI相關(guān)】View的繪制原理 2024-07-19

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í)行之后開始。


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

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

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