天天看點

Android View 布局流程(Layout)完全解析前言ViewGroup的布局流程子View的布局流程

上一篇文章,筆者詳細講述了View三大工作流程的第一個,Measure流程,如果對測量流程還不熟悉的讀者可以參考一下上一篇文章。測量流程主要是對View樹進行測量,擷取每一個View的測量寬高,那麼有了測量寬高,就是要進行布局流程了,布局流程相對測量流程來說簡單許多。那麼我們開始對layout流程進行詳細的解析。

上一篇文章提到,三大流程始于ViewRootImpl#performTraversals方法,在該方法内通過調用performMeasure、performLayout、performDraw這三個方法來進行measure、layout、draw流程,那麼我們就從performLayout方法開始說,我們先看它的源碼:

由上面的代碼可以看出,直接調用了①号的host.layout方法,host也就是DecorView,那麼對于DecorView來說,調用layout方法,就是對它自身進行布局,注意到傳遞的參數分别是0,0,host.getMeasuredWidth,host.getMeasuredHeight,它們分别代表了一個View的上下左右四個位置,顯然,DecorView的左上位置為0,然後寬高為它的測量寬高。由于View的layout方法是final類型,子類不能重寫,是以我們直接看View#layout方法即可:

首先看①号代碼,調用了setFrame方法,并把四個位置資訊傳遞進去,這個方法用于确定View的四個頂點的位置,即初始化mLeft,mRight,mTop,mBottom這四個值,當初始化完畢後,ViewGroup的布局流程也就完成了

那麼,我們先看View#setFrame方法:

可以看出,它對mLeft、mTop、mRight、mBottom這四個值進行了初始化,對于每一個View,包括ViewGroup來說,以上四個值儲存了Viwe的位置資訊,是以這四個值是最終寬高,也即是說,如果要得到View的位置資訊,那麼就應該在layout方法完成後調用getLeft()、getTop()等方法來取得最終寬高,如果是在此之前調用相應的方法,隻能得到0的結果,是以一般我們是在onLayout方法中擷取View的寬高資訊。

在設定ViewGroup自身的位置完成後,我們看到會接着調用②号方法,即onLayout()方法,該方法在ViewGroup中調用,用于确定子View的位置,即在該方法内部,子View會調用自身的layout方法來進一步完成自身的布局流程。由于不同的布局容器的onMeasure方法均有不同的實作,是以不可能對所有布局方式都說一次,另外上一篇文章是用FrameLayout#onMeasure進行講解的,那麼現在也對FrameLayout#onLayout方法進行講解:

由源碼看出,onLayout方法内部直接調用了layoutChildren方法,而layoutChildren則是具體的實作。

先梳理一下以上邏輯:首先先擷取父容器的padding值,然後周遊其每一個子View,根據子View的layout_gravity屬性、子View的測量寬高、父容器的padding值、來确定子View的布局參數,然後調用child.layout方法,把布局流程從父容器傳遞到子元素。

那麼,現在就分析完了ViewGroup的布局流程,那麼我們接着分析子元素的布局流程。

子View的布局流程也很簡單,如果子View是一個ViewGroup,那麼就會重複以上步驟,如果是一個View,那麼會直接調用View#layout方法,根據以上分析,在該方法内部會設定view的四個布局參數,接着調用onLayout方法,我們看看View#onLayout方法:

這是一個空實作,主要作用是在我們的自定義View中重寫該方法,實作自定義的布局邏輯。

那麼到目前為止,View的布局流程就已經全部分析完了。可以看出,布局流程的邏輯相比測量流程來說,簡單許多,擷取一個View的測量寬高是比較複雜的,而布局流程則是根據已經獲得的測量寬高進而确定一個View的四個位置參數。在下一篇文章,将會講述最後一個流程:繪制流程。希望這篇文章給大家對View的工作流程的了解帶來幫助,謝謝閱讀。

更多閱讀 <a href="http://www.jianshu.com/p/3299c3de0b7d" target="_blank">Android View 測量流程(Measure)完全解析</a> <a href="http://www.jianshu.com/p/3e064c045f0f" target="_blank">Android View 繪制流程(Draw) 完全解析</a>     本文轉自 一點點征服   部落格園部落格,原文連結: http://www.cnblogs.com/ldq2016/p/6689092.html ,如需轉載請自行聯系原作者

繼續閱讀