這篇文章只是一個(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的紐帶。

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

performTraversals的工作流程
performTraversals會(huì)依次調(diào)用
- performMeasure---->measure--->onMeasure---->從父容器傳遞到子View
- performLayout ---->layout ---->onLayout--->從從父容器傳遞到子View
- performDraw--->draw---->onDraw--->從父容器傳遞到子View
三 Mearsure,Layout,Draw的工作流程
Mearsure
測(cè)量分為兩種情況
- view 的測(cè)量
- view的測(cè)量是通過(guò)measure的方法來(lái)測(cè)量的
- measure方法調(diào)用了onMeasure方法,傳入?yún)?shù)MeasureSpec,其中 onMeasure方法對(duì)MeasureSpec進(jìn)行處理
- onMeasure方法中調(diào)用了setMeasuredDimension()方法去設(shè)置View的具體寬高值
- getDefaultSize()此方法傳入MeasureSpec,由此來(lái)確定寬高。
- ViewGroup的測(cè)量
1.先遍歷去調(diào)用所有子元素的measure方法,各個(gè)子元素再遞歸去執(zhí)行這個(gè)流程.
- 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ū)別從源碼分析
getMeasuredWidth方法獲得的值是setMeasuredDimension方法設(shè)置的值,它的值在measure方法運(yùn)行后就會(huì)確定
getWidth方法獲得是layout方法中傳遞的四個(gè)參數(shù)中的mRight-mLeft,它的值是在layout方法運(yùn)行后確定的
一般情況下在onLayout方法中使用getMeasuredWidth方法,而在除onLayout方法之外的地方用getWidth方法。
4.在幾乎所有的情況下都是相等的。
draw
這個(gè)過(guò)程就比較簡(jiǎn)單了,就是根據(jù)上面的數(shù)據(jù)進(jìn)行繪制到屏幕上。