簡(jiǎn)介
這篇文章繼續(xù)就上一篇文章【View】- setContentView方法和UI繪制流程(源碼分析)中performLayout方法進(jìn)行講解澜建,了解UI繪制的布局過(guò)程。如果想了解測(cè)量流程,請(qǐng)查看【view】- 測(cè)量流程。
performLayout
讀過(guò)【View】- setContentView方法和UI繪制流程(源碼分析)應(yīng)該知道,performLayout中的mView是頂層布局DecorView另假。
所以首先還是調(diào)用DecorView的layout方法。而DecorView沒(méi)有實(shí)現(xiàn)layout方法怕犁,其父類ViewGroup實(shí)現(xiàn)了浪谴,然后調(diào)用父類View的layout(int l, int t, int r, int b)方法。
在layout會(huì)調(diào)用 onLayout(changed, l, t, r, b)方法因苹,先看一下DecorView中的onLayout方法苟耻。
public void layout(int l, int t, int r, int b) {
//如果不是第一次,跳過(guò)否則會(huì)在此進(jìn)行測(cè)量扶檐,意思是第一次進(jìn)來(lái)會(huì)進(jìn)行一次測(cè)量用于保存寬高凶杖,意義在于優(yōu)化,接著往下看
if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
}
// 初次進(jìn)行上下左右點(diǎn)的初始化
int oldL = mLeft;
int oldT = mTop;
int oldB = mBottom;
int oldR = mRight;
//這里調(diào)用了setFrame進(jìn)行初始化mLeft,mRight,mTop,mBottom這四個(gè)值
boolean changed = isLayoutModeOptical(mParent) ?
setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
onLayout(changed, l, t, r, b);
...
}
...
}
setFrame(int left, int top, int right, int bottom)對(duì)上下左右四個(gè)點(diǎn)坐標(biāo)進(jìn)行初始化款筑。setFrame在進(jìn)行初始化的時(shí)候會(huì)對(duì)比上一次是否一致智蝠,若一致則不會(huì)在此進(jìn)行腾么,若是一致,則會(huì)使我們舊的信息直接失效invalidate(sizeChanged)杈湾。
調(diào)用父類onLayout方法
super.onLayout(changed, left, top, right, bottom);
FrameLayout中的onLayout方法解虱,調(diào)用layoutChildren(int left, int top, int right, int bottom, boolean forceLeftGravity) 方法。layoutChildren經(jīng)過(guò)一系列的計(jì)算漆撞,然后遍歷DecorView所以子View殴泰,然后調(diào)用子View的layout方法,根據(jù)前面將的浮驳,最終調(diào)用子View的onLayout方法悍汛,并把開始布局的位置參數(shù)傳遞給子View。