06.layout布局
layout 流程
在 ViewRootImpl#performTravasls
或调用 performLayout
performLayout 触发的条件:
1
2
3
4
5
6
7
// ...
final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw);
boolean triggerGlobalLayoutListener = didLayout
|| mAttachInfo.mRecomputeGlobalAttributes;
if (didLayout) {
performLayout(lp, mWidth, mHeight);
// ...
- mLayoutRequested 为 true,即调用 requestLayout()
- 触摸模式发生变化
- decorview 宽高发生变化
- 内容边界是否发生变化
- Configuration 发生变化
performlayout 直接调用了 decorView.layout() 方法,即 ViewGroup 的 layout 方法
1
2
3
4
5
6
7
8
9
10
11
12
@Override
public final void layout(int l, int t, int r, int b) {
if (!mSuppressLayout && (mTransition == null || !mTransition.isChangingLayout())) {
if (mTransition != null) {
mTransition.layoutChange(this);
}
super.layout(l, t, r, b);
} else {
// record the fact that we noop'd it; request layout when transition finishes
mLayoutCalledWhileSuppressed = true;
}
}
如果有 Transition 动画在执行则不调用 layout,否则调用 View.layout
View.layout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void layout(int l, int t, int r, int b) {
if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
}
int oldL = mLeft;
int oldT = mTop;
int oldB = mBottom;
int oldR = mRight;
boolean changed = isLayoutModeOptical(mParent) ?
setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
onLayout(changed, l, t, r, b);
}
}
本文由作者按照 CC BY 4.0 进行授权