onMeasure()
是您有机会告诉Android您希望自定义视图的大小取决于父级提供的布局约束;这也是您的自定义视图的机会,可以了解这些布局约束条件(如果您希望在match_parent
情况下的行为与wrap_content
情况下的行为不同)。这些约束被打包到传入该方法的MeasureSpec
值中。下面是模式值的粗略的相关性:
- EXACTLY指
layout_width
或layout_height
值设定为特定值。你可能应该让你的观点大小。当使用match_parent
时,也可以触发这种情况,以将尺寸精确地设置为父视图(这与框架中的布局相关)。
- AT_MOST通常表示
layout_width
或layout_height
值设定为match_parent
wrap_content
或其中需要的最大尺寸(这是布局依赖于框架),并且父维度的大小的值。你不应该大于这个尺寸。
- 未知通常表示
layout_width
或layout_height
值设置为wrap_content
,没有任何限制。你可以是任何你想要的大小。某些布局还会使用此回调来确定您希望的尺寸,然后再决定在第二个度量请求中实际再次传递给您的参数。
与onMeasure()
存在的契约是:setMeasuredDimension()
MUST在与大小结束时调用你想的观点是。此方法由所有框架实现调用,包括在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);
}
希望帮助。
嘿@Devunwired很好的解释迄今为止我读的最好的。你的解释回答了我的许多问题,并清除了一些疑问,但仍有一个问题仍然存在:如果我的自定义视图位于ViewGroup中,并且其他视图(无论哪种类型)ViewGroup将其所有子项为每个探测器的LayoutParams约束,并要求每个孩子根据自己的约束来自我测量? – pharaoh
是的,这就是'ViewGroup'的'measureChildren()'方法在度量/布局过程中所做的。 – Devunwired
请注意,如果您重写任何ViewGroup子类的onMeasure,则此代码不会执行此操作。你的子视图不会显示出来,全部大小都为0x0。如果您需要重写自定义ViewGroup的onMeasure,请更改widthMode,widthSize,heightMode和heightSize,然后使用MeasureSpec.makeMeasureSpec将它们编译回measureSpecs,并将生成的整数传递给super.onMeasure。 – Alexey