Layout is a two pass process: a measure pass and a layout pass. The measuring pass is implemented in measure(int,
int) and is a top-down traversal of the view tree. Each view pushes dimension specifications down the tree during the recursion. At the end of the measure pass, every view has stored its measurements. The second pass happens in layout(int,
int, int, int) and is also top-down. During this pass each parent is responsible for positioning all of its children using the sizes computed in the measure pass.
(View)的布局分兩步進行:測量過程和版面配置階段。測量過程就是使用measure方法和從上往下遍曆view樹進行的。每一個view通過遞迴的方式在view樹上從上往下確定自己的尺寸參數(這句翻譯感覺欠妥),在測量過程結束時,每一個view都儲存了他自己的尺寸值。第二個過程是伴隨layout()方法開始的,也是一個從上往下的過程。在這個過程中,每一個父view需要根據測量過程得到的尺寸值來合理地安排子view的大小和位置。
When a view's measure() method returns, its getMeasuredWidth() and getMeasuredHeight() values
must be set, along with those for all of that view's descendants. A view's measured width and measured height values must respect the constraints imposed by the view's parents. This guarantees that at the end of the measure pass, all parents accept all of
their children's measurements. A parent view may call measure() more than once on its children. For example, the parent may measure each child once with unspecified dimensions to find out how big they want to be, then call measure() on them again with actual
numbers if the sum of all the children's unconstrained sizes is too big or too small.
當一個view的measure()方法返回時,它的getMeasuredWidth() and getMeasuredHeight() 值必須被設定成功(感覺可以理解為它的getMeasuredWidth() and getMeasuredHeight() 方法都能有傳回值了,也就是measure方法測量成功了。),同時該view的子view也已經被測量成功。一個view的測量後的寬度和高度必須服從它的父view給定的大小約束才行。這樣才能保證在測量結束後,所有的父view能夠接受它們所有的子控制項。一個父view可能多次調用measure()來測量子view的尺寸。例如,父view第一次測量它的子view的尺寸來得到子view實際想要的大小,(如果這個子view的大小不符合要求,太大或太小)父view會第二次調用measure來重新確定子view的大小。
下面這一部分不翻譯了。網路上很多人翻譯得比我好多了,我這裡就不誤人子弟了。哈哈
The measure pass uses two classes to communicate dimensions. The View.MeasureSpec class is used by views
to tell their parents how they want to be measured and positioned. The base LayoutParams class just describes how big the view wants to be for both width and height. For each dimension, it can specify one of:
- an exact number
- MATCH_PARENT, which means the view wants to be as big as its parent (minus padding)
- WRAP_CONTENT, which means that the view wants to be just big enough to enclose its content (plus padding).
There are subclasses of LayoutParams for different subclasses of ViewGroup. For example, AbsoluteLayout has its own subclass of LayoutParams which adds an X and Y value.
MeasureSpecs are used to push requirements down the tree from parent to child. A MeasureSpec can be in one of three modes:
- UNSPECIFIED: This is used by a parent to determine the desired dimension of a child view. For example, a LinearLayout may call measure() on its child with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
tall the child view wants to be given a width of 240 pixels.
- EXACTLY: This is used by the parent to impose an exact size on the child. The child must use this size, and guarantee that all of its descendants will fit within this size.
- AT_MOST: This is used by the parent to impose a maximum size on the child. The child must gurantee that it and all of its descendants will fit within this size.
To intiate a layout, call requestLayout(). This method is typically called by a view on itself when
it believes that is can no longer fit within its current bounds.