先来看看官方文档对方法的描述。
onMeasure
void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
测量View和它的内容来确定measured width和measured height,这个方法被measure(int, int)
调用,而且会被子类重写来准确高效的测量他们的内容。
约定事项: 当重写这个方法的时候,必须调用setMeasuredDimension(int, int)
来存储这个View的measured width和measured height,否则measure(int, int)
会触发 IllegalStateException
。直接使用父类的on measure(int, int)
是可以的。
基类默认是测量背景的尺寸(看下面源码)。子类应该重写'onMeasuer(int, int)' 来提供更好的测量方法来测量他们的内容。
如果这个方法被重写,它的子类要保证测量高度和宽度至少是view的最小高宽。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
//如果没有指定
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
//获取背景的最小宽
protected int getSuggestedMinimumWidth() {
return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
}
//获取背景的最小高
protected int getSuggestedMinimumHeight() {
return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
}
Measure
void measure (int widthMeasureSpec, int heightMeasureSpec)
找出View有多大的时候调用这个方法,参数是父类提供的约束信息。
实际的测量工作是在通过调用onMeasure(int, int)
完成的。因此只有‘onMeasure(int, int)’能被重写。
下面看看MeasureSpec的参数,MeasureSpec包含大小和模式,它有3种模式:
UNSPECIFIED
,父控件不强制约束子控件,子控件可以任意大小;
EXACTLY
,父控件已经给子控件的一个确定的大小,无论子控件多大都被限制在这个边界内
AT_MOST
,子控件至多达到指定大小。
父控件的约束规则 子控件的宽高属性 子控件的约束规则 说明
EXACTLY(父控件是填充父窗体,或者具体size值) 具体的size(20dip)/MATCH_PARENT EXACTLY 子控件如果是具体值,约束尺寸就是这个值,模式为确定的;子控件为填充父窗体,约束尺寸是父控件剩余大小,模式为确定的。
父控件的约束规则 | 子控件的宽高属性 | 子控件的约束规则 | 说明 |
---|---|---|---|
EXACTLY(父控件是填充父窗体,或者具体size值) | 具体的size(20dip)/MATCH_PARENT | EXACTLY | 子控件如果是具体值,约束尺寸就是这个值,模式为确定的;子控件为填充父窗体,约束尺寸是父控件剩余大小,模式为确定的。 |
WRAP-CONTENT | AT_MOST | 子控件如果是包裹内容,约束尺寸值为父控件剩余大小 ,模式为至多 | |
AT_MOST(父控件是包裹内容) | 具体的size(20dip) | EXACTLY | 子控件如果是具体值,约束尺寸就是这个值,模式为确定的; |
MATCH_PARENT/WRAP_CONTENT | AT_MOST | 子控件为填充父窗体或者包裹内容 ,约束尺寸是父控件剩余大小 ,模式为至多 | |
UNSPECIFIED(父控件未指定) | 具体的size(20dip) | EXACTLY | 子控件如果是具体值,约束尺寸就是这个值,模式为确定的; |
MATCH_PARENT/WRAP_CONTENT | UNSPECIFIED | 子控件为填充父窗体或者包裹内容 ,约束尺寸0,模式为未指定 |
网友评论