** 注:本文參考鏈結how android caculates view size計算view大小的過程可以分為以下幾個步驟:本文例子如下所示:
確定view想要的size(layoutparams)
確定parent view的情況(measurespec)
在parent view的限制下,根據view的layoutparams,確定view的大小
layoutparams用於view表示想要的size的模式。有以下三種:
fill_parent / match_parent (-1)
view的size和parent view的size一樣大
wrap_content(-2)
view的size僅包裹其內容即可
指定的值(>0)
view的size為指定的size大小
measurespec表示當前view的「約束」(在onmeasure中傳入)。約束含模式mode和數值size,當前view根據mode來決定如何看待其中的size。mode有三種,如下所示:
unspecified
對當前view的size沒有約束
exactly
當前view的bounds(可以理解成「可以使用的範圍」)為確定的size,也可以理解成parent view希望當前view(有強制的意味)使用給定的size
at_most
當前view的大小不可超過指定的size
可以利用measurespec的getmode取出具體值.size為8個byte的int值,mode放在前2個bit中。這裡可以利用measurespec的getsize取出size的具體值。
view通過onmeasure確定自己的大小。確定自己的大小時,需要的東西有:
約束measurespec
自己的layoutparams
如果有child view,那麼需要獲取child view的大小
最終確定當前view的size分別為:
measurewidth
measureheight
以前面例子中的textview為例,其onmeasure中傳入的measurespec為:
width
mode:at_most size:parentcontentwidth(linearlayout的寬-padding)
height
mode:unspecified size:不確定
注:這裡先不解釋為什麼measurespec是這樣的。
textview的layoutparams為:
width
match_parent
height
wrap_content
然後textview根據約束和layoutparams確定自己的大小,包括但不限於以下過程:
設定寬度為parentcontentwidth,考慮margin確定字元可用範圍
根據字元高度和字型設定(根據是否超過parentcontentwidth確定是否換行)等計算字元所佔的高度(沒有限制)。
設定measurewidth和measureheight
以前面例子中的linearlayout為例,假設該linearlayout為activity中的root layout其onmeasure中傳入的measurespec為:
width
mode:exactly size:parentcontentwidth(linearlayout的parent view的寬-padding)
height
mode:at_most size:parentcontentheight(linearlayout的parent view的高-padding)
relativelayout的layoutparams為:
width
match_parent
height
wrap_content
orientation
vertical
然後linearlayout根據約束和layoutparams確定自己的大小,包括但不限於以下過程:
確定child view的排列方式
確定textview的size
確定imageview的size
根據自身的設定,設定measurewidth和measureheight
要確定child view的size,就要呼叫child view的onmeasure,傳入合適的measurespec,表明parent view對child的約束。
根據parent view的不同module和child view的不同layoutparams,有如下規則:
當parent view的mode是exactly時:
child layout
mode
size
exact size
exactly
childsize
child wants a specific size.
match_parent
exactly
parentcontentsize
child wants to be parent's size.
wrap_content
at_most
parentcontentsize
child wants to determine its own size. it can not be bigger than parent.
當parent view的mode是at_most時:
child layout
mode
size
exact size
exactly
childsize
child wants a specific size
match_parent
at_most
parentcontentsize
child wants to be parent's size, but parent's size is not fixed. constrain child to not be bigger than parent.
wrap_content
at_most
parentcontentsize
child wants to determine its own size, but it can not be bigger than parent.
當parent view的mode是unspecified時:
child layout
mode
size
exact size
exactly
childsize
child wants a specific size.
match_parent
unspecified
can not decide yet
child wants to be parent's size. child will decide its own size later.
wrap_content
unspecified
can not decide yet
child wants to be its own size. child will decide its own size later.
以例子中的textview為例:
linearlayout的width mode為exactly,textview的width layout param為match_parent
linearlayout的height mode為at_most,textview的height layout param為wrap_content
所以textview的onmeasure會被傳入:
width
mode:exactly size:parentcontentwidth(linearlayout的寬-padding)
height
mode:at_most size:parentcontentheight(linearlayout的高-padding)
textview可以根據上述約束計算自己的大小。imageview同理。最後linearlayout根據imageview和textview的大小計算自己的大小。注意這裡沒有weight的設定,所以onmeasure只執行一次。
Android 如何計算View的Size
注 本文參考鏈結how android caculates view size 本文例子如下所示 計算view大小的過程可以分為以下幾個步驟 確定view想要的size layoutparams 確定parent view的情況 measurespec 在parent view的限制下,根據view...
Android如何計算View的深度
今天在qq群上,看到大家談到了乙個面試題,就是如何求view樹的深度。在我們專案中基本上比較少需要到這個計算,所以可能一下子會蒙圈了。我們知道,android的檢視是一顆樹的形式,那麼即使關於android的view樹方面很多計算,便可以利用樹的原理來計算。談到樹,我們在書本上最常看到的就是二叉樹,...
開發者指南 Android如何繪製View
android畫的操作是由framework層來進行處理的,整個 draw是從根view開始的,viewgroup向子view發出 draw的請求,然後子view負責自己重畫它們的invalid區域。drawing乙個layout必須通過兩個步驟 1.測量。measure 從根節點到葉子節點依次測量...