開發者意見->父view意見->本身去測量->父view拿到實際尺寸位置,調用layout方法佈局
運行前,開發者在xml文件寫入對view的要求xml
父view在本身的onMeasure中根據開發者在xml中寫對子view的要求,和本身的可用空間得出對子view的要求繼承
子view在本身的onMeasure中,根據本身的特性算出本身指望的尺寸遞歸
① 若是是ViewGroup,還會調用每一個子view的measure進行測量開發
父view在子view計算出指望尺寸後,得出子view的實際尺寸和位置get
子view在本身的layout方法中,將父view傳進來的本身的實際尺寸和位置保存it
① 若是是VIewGroup,還會在onLayout裏面調用每一個子view的layout把它們的尺寸位置傳遞給他們io
重寫onMeasureclass
getMeasuredWidth和getMeasuredSize獲取到測量出的尺寸遍歷
計算出最終須要的尺寸
setMeasureDimension(width,height)把結果保存
重寫onMeasure
計算出本身的尺寸
用resolveSize或則resolveSizeAndState修正結果
內部實現:
① 首先用MeasureSpec.getMode(measureSpec)和MeasureSpec.getSize(MeasureSpec)去出對本身的尺寸限制類型和限制尺寸
② 若是measureSpec的mode是EXACTLY,表示父view對子view的尺寸作出了精的限制,直接用measureSpec的size
③ 若是measureSpec的mode是AT_MOST,表示父view對子view的尺寸只限制了上限,要具體看狀況
size不大於spec限制的size,即是沒有超限,選用計算出的size
size大於spec限制的size,超限了,選用spec的size
mode是UNSPECIFIED,表示父view對子view沒有任何尺寸限制,直接選用計算的size
使用setMeasuredDimension(width,height)保存結果
重寫onMeasure
① 遍歷每一個子view,用measureChildWidthMargins測量子view
須要重寫generateLayoutParams並返回MarginLayoutParams才能使用measureChildWithMargins方法
有些子view須要從新測量 當換行時須要
測量完成後,得出子View的實際位置和尺寸,並暫時保存
① measureChildWidthMargins的內部實現
經過getChildMeasureSpec方法算出子view的widthMeasureSpec和heightMeasureSpec,而後調用child.measure方法讓子view自我測量
getChildMeasureSpec方法內部是現實結合開發者設置的LayoutParams中的width和heigth與父view本身的可用空間,得出對子view的限制,並使用MeasureSpec.makeMeasureSpec來求得結果
② 測量出全部子view的位置和尺寸後,計算出本身的尺寸,並用setMeasuredDimension保存
重寫onLayout
遍歷每一個子view,調用他們的layout方法來將位置和尺寸傳給他們
有些父view會對子view進行糾正,如constraintLayout就會強行糾正你自定view的長和寬
通常沒人重寫layout方法
onLayout負責遞歸對子view進行賦值,和layout方法不同
測量的過程也能夠換一種方法來理解
① 若是開發者寫了具體值(例如 layout_width="24dp"),就不用再考慮父View 的剩餘空間了,直接用 LayoutParams.width / height 來做爲子 View的限制 size,而限制 mode 爲 EXACTLY,由於衝突致使界面不正確,開發者能夠經過修改 xml 文件來解決,因此開發者的意見是第一位
② 若是開發者寫的是 MATCH_PARENT,即要求填滿父控件的可用空間,那麼因爲本身的可用空間和本身的兩個 MeasureSpec 有關,因此須要根據本身的 widthMeasureSpec 或 heightMeasureSpec 中的 mode 來分狀況判斷:
③ 若是開發者寫的是 WRAP_CONTENT,即要求子 View 在不超限制的前提下自我測量,那麼一樣因爲本身的可用空間和本身的兩個 MeasureSpec 有關,因此也須要根據本身的 widthMeasureSpec 和 heightMeasureSpec中的 mode 來分狀況判斷: