View框架之measure 流程

2021-07-24 06:18:09 字數 4201 閱讀 4346

注意:1.以下measurespec用ms來代替(ms具體會在後面介紹)

2.該時序圖描述的是從viewrootimpl開始的measure()過程,因為viewrootimpl是window與view連線的樞紐

3.該時序圖著重於大概流程及重要方法的作用,具體**細節會放到後面介紹

4.decorview作為頂級view,本身是乙個framelayout,所以也是乙個viewgroup

在view的測量過程中,ms起著非常重要的作用,ms在某種程度上來說更像是一種測量的標準。

ms是乙個32位的int值,前2位代表測量模式,後30位代表測量大小

測量模式(specmode)一共分為3種:

unspecified: 父容器不對子view限制,這種情況一般我們用不到,系統內部使用

exactly : 父容器可以算出view的具體的大小,一般對應於 具體值或者match_parent

at_most : 父容器指定乙個值,子view不能超過這個值,一般對應於 wrap_content

一般情況下,乙個view的ms的測量是根據父容器的ms和本身的layoutparams來決定的,根據一些規則,在父容器中算出ms,然後父容器呼叫此view的measure()方法將結果傳給該view,該view接著會回掉onmeasure()將結果傳給該view的實現類。  但是decorview作為頂級view是沒有父容器的,所以decorview的ms是根據視窗的大小和自身的layoutparams來決定的。
--

/*** desirewindowwidth : 代表螢幕的寬頻 ,同理,dwh 代表螢幕的高度

**/private boolean measurehierarchy(final view host, final windowmanager.layoutparams lp,

final resources res, final int desiredwindowwidth, final int desiredwindowheight)

/*** 計算出decorview的ms*

**/private static int getrootmeasurespec(int windowsize, int rootdimension)

return measurespec;

protected void measurechildwithmargins(view child,

int parentwidthmeasurespec, int widthused,

int parentheightmeasurespec, int heightused)

//根據父容器的ms和自身的layoutparams求出該view的ms的具體操作

public static int getchildmeasurespec(int spec, int padding, int childdimension) else if (childdimension == layoutparams.match_parent) else if (childdimension == layoutparams.wrap_content)

break;

// parent has imposed a maximum size on us

case measurespec.at_most:

if (childdimension >= 0) else if (childdimension == layoutparams.match_parent) else if (childdimension == layoutparams.wrap_content)

break;

// parent asked to see how big we want to be

case measurespec.unspecified:

if (childdimension >= 0) else if (childdimension == layoutparams.match_parent) else if (childdimension == layoutparams.wrap_content)

break;

}return measurespec.makemeasurespec(resultsize, resultmode);

}

一般view的measure()方法如下:

public final void measure(int widthmeasurespec, int heightmeasurespec) else

// flag not set, setmeasureddimension() was not invoked, we raise

// an exception to warn the developer

if ((mprivateflags & pflag_measured_dimension_set) != pflag_measured_dimension_set)

mprivateflags |= pflag_layout_required;

}

// 將ms值儲存起來,為了提高效能,如果下次進來並且標誌沒變,就不會再重複執行onmeasure()

moldwidthmeasurespec = widthmeasurespec;

moldheightmeasurespec = heightmeasurespec;

mmeasurecache.put(key, ((long) mmeasuredwidth) << 32 |

(long) mmeasuredheight & 0xffffffffl); // suppress sign extension

}viewgroup 的 measure();

view是乙個容器,他不但要完成自己的測量方法,還需要遍歷onmeasure()計算出下一層級的ms,下面以framelayout的onmeasure方法為講解

@override

protected void onmeasure(int widthmeasurespec, int heightmeasurespec) }}

}// account for padding too

maxwidth += getpaddingleftwithforeground() + getpaddingrightwithforeground();

maxheight += getpaddingtopwithforeground() + getpaddingbottomwithforeground();

// check against our minimum height and width

maxheight = math.max(maxheight, getsuggestedminimumheight());

maxwidth = math.max(maxwidth, getsuggestedminimumwidth());

// check against our foreground's minimum height and width

final drawable drawable = getforeground();

if (drawable != null)

setmeasureddimension(resolvesizeandstate(maxwidth, widthmeasurespec, childstate),

resolvesizeandstate(maxheight, heightmeasurespec,

childstate << measured_height_state_shift));

count = mmatchparentchildren.size();

if (count > 1) else

if (lp.height == layoutparams.match_parent) else

//呼叫子類的measure()方法進行傳遞

child.measure(childwidthmeasurespec, childheightmeasurespec);}}

}

View工作原理 Measure過程

知識點 view的measure過程和activity的生命週期不同步 一 view的measure過程 measure是final,不可重寫 measure onmeasure setmeasureddimension getdefaultsize這裡atmost和exactly進行了相同的操作 ...

普通View的measure流程

對於普通的view,其測量在viewgroup中的measurechildwithmargins函式中呼叫child view的measure開始測量。1 從measure函式開始 1 public final void measure int widthmeasurespec,int height...

View框架之layout 流程

注意 rootview是乙個framelayout,所以也是乙個viewgroup 這裡的的host就是我們的根布局decorview,因為decorview是乙個framelayout,而layout 是view中被修飾final的方法,所以我們這裡呼叫的是view的layout的方法,layou...