1.onLayout
android.view.ViewGroup
protected void onLayout(boolean changed, int l, int t, int r, int b)
执行layout操作时调用onLayout方法。View要给它的每个Child设定size和position。拥有Children的子类需要重写onLayout方法并且调用每个Child的layout方法。
参数changed表示view的size或position发生变化。参数l, t, r, b分别表示相对于parent的left, top, right, bottom position。
2.onMeasure
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
测量View及其Content,确定measuredWidth和measuredHeight。在方法measure(int, int)中调用。重写onMeasure方法时,需要调用方法setMeasuredDimension(int, int),存储View的measuredWidth和measuredHeight。若存储失败,方法measure(int, int)会抛出异常IllegalStateException。可以调用super.onMeasure(int, int)方法。
除非MeasureSpec准许更大的size,否则measure的默认实现是background size。子类重写onMeasure(int, int)提供Content的更佳测量。如果onMeasure被重写,子类必须保证measuredWidth和measuredHeight至少是view的minHeight和minWidth。minHeight/Width通过getSuggestedMinimumHight/Width()获取。
参数width/heightMeasureSpec表示parent强加的horizontal/vertical space要求。
void android.view.ViewGroup.layout(int l, int t, int r, int b)
给view及其descendants设定size和position。它正是layout机制的第2个步,每个parent调用它的chlidren的layout操作。使用在measure阶段测量得到的size和position数据完成layout操作。拥有child的子类必须重写onLayout方法,调用每个child的layout操作。
void android.view.ViewGroup.measureChildren(int widthMeasureSpec, int heightMeasureSpec)
请View的所有children测量themseles, 测量依据是View的MeasureSpec和padding。忽略处于GONE状态的children,是否GONE状态由getChildMeasureSpec来确定。
参数width/heightMeasureSpec表示view的width/height要求。
3.MeasureSpec
android.view.View.MeasureSpec
MeasureSpec是View的内部类
public static class MeasureSpec
MeasureSpec封装从parent传递给child的layout要求。每个MeasureSpec表示对width/height的要求。MeasureSpec由size和mode组成。可用的mode有3种:
1. UNSPECIFIED表示parent没有强加给child任何constraint。
2. EXACTLY表示parent已经确定child的精确size。
3. AT_MOST表示child可以设定为specified size之内的任何值。
MeasureSpec实现为int类型,相比object类型,降低了allocation。可以将<size, mode>元组pack和unpack为int类型。
MeasureSpec定义的常量有:
private static final int MODE_SHIFT = 30;
private static final int MODE_MASK = 0x3 << MODE_SHIFT;
public static final int UNSPECIFIED = 0 << MODE_SHIFT;
public static final int EXACTLY = 1 << MODE_SHIFT;
public static final int AT_MOST = 2 << MODE_SHIFT;
MeasureSpec定义的方法有:
public static String toString(int measureSpec) {
int mode = getMode(measureSpec);
int size = getSize(measureSpec);
StringBuilder sb = new StringBuilder("MeasureSpec: ");
if (mode == UNSPECIFIED)
sb.append("UNSPECIFIED ");
else if (mode == EXACTLY)
sb.append("EXACTLY ");
else if (mode == AT_MOST)
sb.append("AT_MOST ");
else
sb.append(mode).append(" ");
sb.append(size);
return sb.toString();
}
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
public static int makeMeasureSpec(int size, int mode) {
return size + mode;
}