onMeasure()
您是否有机会告诉 Android 您希望自定义视图依赖于父级提供的布局约束有多大?这也是您的自定义视图有机会了解这些布局约束是什么(如果您想在某种match_parent
情况下表现得不同wrap_content
)。这些约束被打包到MeasureSpec
传递给方法的值中。以下是众数值的粗略相关性:
- EXACTLY表示
layout_width
orlayout_height
值已设置为特定值。你可能应该把你的视图设为这个大小。这也可以在match_parent
使用时触发,以将大小精确设置为父视图(这取决于框架中的布局)。
- AT_MOST通常意味着
layout_width
orlayout_height
值被设置为match_parent
或wrap_content
需要最大尺寸的地方(这取决于框架中的布局),并且父维度的大小是该值。你不应该比这个尺寸大。
- UNSPECIFIED通常意味着
layout_width
orlayout_height
值被设置为wrap_content
没有限制。你可以是任何你想要的尺寸。一些布局还使用此回调来确定您想要的尺寸,然后再确定在第二次测量请求中实际再次传递给您的规格。
存在的合同onMeasure()
是setMeasuredDimension()
必须在最后以您希望视图的大小调用。所有框架实现都会调用此方法,包括在 中找到的默认实现View
,这就是为什么super
如果适合您的用例,则可以安全地调用此方法。
当然,因为框架确实应用了默认实现,所以您可能没有必要重写此方法,但是如果您不这样做,并且如果您布置了您的两个方向的自定义视图wrap_content
,您的视图可能根本不会显示,因为框架不知道它有多大!
通常,如果您正在覆盖View
而不是另一个现有的小部件,那么提供一个实现可能是一个好主意,即使它像这样简单:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = 100;
int desiredHeight = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}
希望有帮助。