View的工作原理淺談(知識(shí)總結(jié))

這篇文章只是一個(gè)簡(jiǎn)單自定義知識(shí)總結(jié),淺談自定義View。
在學(xué)習(xí)自定義View之前我們先了解一下幾個(gè)概念。

一 ViewRoot,DecorView

ViewRoot是什么? ViewRoot對(duì)應(yīng)于ViewRootImpl類,看到了很多人寫的是viewtree的根節(jié)點(diǎn),其實(shí)它跟View沒(méi)有任何關(guān)系,也不是ViewTree的根節(jié)點(diǎn),ViewTree的根節(jié)點(diǎn)往往是DecorView,DecorView的根是PhoneWindow,所以ViewRoot不是ViewTree的根節(jié)點(diǎn),ViewRoot將DecorView attach到PhoneWindow上,連接WindowManager和DecorView的紐帶。


742015-20160507011816138-502436220 (1).png

二 View的繪制流程概括

View的繪制流程是從ViewRoot的performTraversals方法開(kāi)始,然后調(diào)用onmeasure,onlayout,ondraw最終繪制出來(lái)view。(此處不做深入探討,以后會(huì)分析)


X)W_JJ7O57M%$E8F71_1NOA.png
performTraversals的工作流程

performTraversals會(huì)依次調(diào)用

  • performMeasure---->measure--->onMeasure---->從父容器傳遞到子View
  • performLayout ---->layout ---->onLayout--->從從父容器傳遞到子View
  • performDraw--->draw---->onDraw--->從父容器傳遞到子View

三 Mearsure,Layout,Draw的工作流程

Mearsure

測(cè)量分為兩種情況

  • view 的測(cè)量
  1. view的測(cè)量是通過(guò)measure的方法來(lái)測(cè)量的
  2. measure方法調(diào)用了onMeasure方法,傳入?yún)?shù)MeasureSpec,其中 onMeasure方法對(duì)MeasureSpec進(jìn)行處理
  3. onMeasure方法中調(diào)用了setMeasuredDimension()方法去設(shè)置View的具體寬高值
  4. getDefaultSize()此方法傳入MeasureSpec,由此來(lái)確定寬高。
  • ViewGroup的測(cè)量
    1.先遍歷去調(diào)用所有子元素的measure方法,各個(gè)子元素再遞歸去執(zhí)行這個(gè)流程.
  1. ViewGroup結(jié)合自己的特性(比如豎直,水平等)給出自身的measure值。
    這里有一個(gè)重要的類需要解釋那就是MeasureSpec
MeasureSpec

(選自開(kāi)發(fā)藝術(shù)探索)
MeasureSpec代表一個(gè)32位int值,高2位代表SpecMode,低30位代表SpecSize,SpecMode是指測(cè)量模式,而specSize是指在某種測(cè)量模式下的規(guī)格大小。
其中SpecMode有三個(gè)類

  • UNSPECIFIED

父容器不對(duì)View有任何限制,要多大給多大,這種情況一般用于系統(tǒng)內(nèi)部,表示一種測(cè)量的狀態(tài)。

  • EXACTLY

父容器已經(jīng)測(cè)量出View所需要的精確大小,這個(gè)時(shí)候View的最終大小就是SpecSize所指定的值。它對(duì)應(yīng)于LayoutParams中的match_parent(填充父元素,因?yàn)楦冈氐拇笮∈枪潭ǖ乃砸蚕喈?dāng)于是具體數(shù)值)和具體的數(shù)值這兩種模式。

  • AT_MOST

父容器指定了一個(gè)可用大小即SpecSize,View大小不能大于這個(gè)值,(就是有最大限制)具體是什么值要看不同View的具體實(shí)現(xiàn)。它對(duì)應(yīng)于LayoutParams中的Wrap_content

Layout

用來(lái)確定子元素的位置,當(dāng)ViewGroup的位置被確定后,它在onLayout中會(huì)遍歷所有的子元素并調(diào)用自身的layout方法,在layout方法中onLayout方法會(huì)被調(diào)用。layout方法確定View本身的位置,onLayout方法則會(huì)確定所有子元素的位置。

這里有一個(gè)小問(wèn)題需要解釋一下就是:getMeasuredHeight(getMeasuredWidth),和getHeight(getWidth)的區(qū)別

友情鏈接:Android開(kāi)發(fā)之getMeasuredWidth和getWidth區(qū)別從源碼分析

  1. getMeasuredWidth方法獲得的值是setMeasuredDimension方法設(shè)置的值,它的值在measure方法運(yùn)行后就會(huì)確定

  2. getWidth方法獲得是layout方法中傳遞的四個(gè)參數(shù)中的mRight-mLeft,它的值是在layout方法運(yùn)行后確定的

  3. 一般情況下在onLayout方法中使用getMeasuredWidth方法,而在除onLayout方法之外的地方用getWidth方法。

4.在幾乎所有的情況下都是相等的。

draw

這個(gè)過(guò)程就比較簡(jiǎn)單了,就是根據(jù)上面的數(shù)據(jù)進(jìn)行繪制到屏幕上。

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

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

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