ViewRootImpl -> performTraversals
private void performTraversals() {
...
performMeasure();
performLayout();
performDraw();
...
}
ViewRootImpl -> performLayout
private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
int desiredWindowHeight) {
...
host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
...
}
host.layout() -> View.layout()
View -> layout
public void layout(int l, int t, int r, int b) {
...
onLayout(changed, l, t, r, b);
...
}
View -> onLayout
/**
* Called from layout when this view should
* assign a size and position to each of its children.
*
* Derived classes with children should override
* this method and call layout on each of
* their children.
* @param changed This is a new size or position for this view
* @param left Left position, relative to parent
* @param top Top position, relative to parent
* @param right Right position, relative to parent
* @param bottom Bottom position, relative to parent
*/
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
}
Derived classes with children should override -> 当存在子类时应该重写
即当自定义 View 继承自 ViewGroup 时,需要重写 onLayout 方法
以 LinearLayout 为例子
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (mOrientation == VERTICAL) {
layoutVertical(l, t, r, b);
} else {
layoutHorizontal(l, t, r, b);
}
}
LinearLayout -> layoutVertical
void layoutVertical(int left, int top, int right, int bottom) {
...
for (int i = 0; i < count; i++) {
if (child == null) {
childLeft += measureNullChild(childIndex);
} else if (child.getVisibility() != GONE) {
...
setChildFrame(child, childLeft, childTop + getLocationOffset(child),
childWidth, childHeight);
childTop += childHeight + lp.bottomMargin + getNextLocationOffset(child);
...
}
}
...
}
LinearLayout -> setChildFrame
private void setChildFrame(View child, int left, int top, int width, int height) {
child.layout(left, top, left + width, top + height);
}
在 visibility != GONE 的情况下会去摆放子 View 的位置。LinearLayout 会循环叠加 top
可以猜想一下 layoutHorizontal 方法就会叠加 left
LinearLayout -> layoutHorizontal
void layoutHorizontal(int left, int top, int right, int bottom) {
...
for (int i = 0; i < count; i++) {
if (child == null) {
childLeft += measureNullChild(childIndex);
} else if (child.getVisibility() != GONE) {
...
setChildFrame(child, childLeft + getLocationOffset(child), childTop,
childWidth, childHeight);
childLeft += childWidth + lp.rightMargin +
getNextLocationOffset(child);
...
}
}
...
}
和猜想的差不多

总结
如果继承自 View 就不用实现 onLayout 方法,如果继承自 ViewGroup 就需要实现 onLayout 方法。Layout 流程是确定和摆放子 View 在父容器中的位置。
网友评论