子View的MeasureSpec的值是由(子View的布局參數(shù)(LayoutParams)和父容器的MeasureSpec值)計(jì)算得來的险绘,具體邏輯
/*
*@paramspec? 父View的詳細(xì)測量值
*@parampadding? View當(dāng)前尺寸的內(nèi)邊距和外邊距
*@paramchildDimension? 子視圖的布局參數(shù)
*@returna MeasureSpec integer for the child
*/
public static intgetChildMeasureSpec(intspec, intpadding, intchildDimension)
根據(jù)View的類型measure過程主要分為兩種情況
(1)單一View的measure過程
1. measure過程:該方法被final修飾佃延,不可以被覆寫
基本測量邏輯的判斷(先判斷是否是強(qiáng)制測量鸣个、測量模式改變了沒有蔓钟,再判斷是否強(qiáng)制測量磺箕、忽略緩存)
if (是否強(qiáng)制測量? ||? 是否需要重新測量(測量模式有沒有改變)) {
if (mMeasureCache緩存中沒有取到值 || 是否忽略緩存) {
onMeasure();
}
}
2. onMeasure()過程:
setMeasureDimension()
getDefaultSize()
getSuggestedMinimumWidth()
因此:在自定義控件時(shí)候稽屏,如果沒有重寫onMeasure方法扮宠,同時(shí)給控件設(shè)置wrap_content屬性時(shí),控件默認(rèn)會顯示match_parent效果狐榔。
其中:
mMeasureCache中存儲通過傳入的widthMeasureSpec和heightMeasureSpec計(jì)算得出的key值信息坛增,即view的信息获雕。
(longkey = (long) widthMeasureSpec <<32| (long) heightMeasureSpec &0xffffffffL;)
mPrivateFlags用于記錄了View的各種狀態(tài)位。
(2)ViewGroup的measure過程
1. measureChildren()
for (遍歷ViewGroup中的所有子View) {
if (View不是GONE狀態(tài)) {
measureChild()
}
}
2.measureChild()
measureSpec = 通過getChildMeasureSpec()方法獲取到當(dāng)前Child的MeasureSpec的值
measure(measureSpec);
3.? getChildMeasureSpec()??
根據(jù)父布局的MeasureSpec和當(dāng)前View的尺寸決定當(dāng)前View的MeasureSpec
4.? measure()
總結(jié)
單一View的measure過程與ViewGroup過程最大的不同:單一View對onMeasure()具有統(tǒng)一的實(shí)現(xiàn)轿偎,而ViewGroup沒有
若LinearLayout的子View設(shè)置了weight典鸡,會進(jìn)行兩次measure計(jì)算,會比較耗時(shí)坏晦,所有當(dāng)LinearLayout的子View需要使用weight的時(shí)候萝玷,最好替換成RelativeLayout布局