Android 自定义视图中的 widthMeasureSpec 和 heightMeasureSpec 是用于测量视图宽度和高度的重要参数。在 Android 中,视图的宽度和高度是通过 MeasureSpec 来确定的。MeasureSpec 是一个 32 位的 int 值,其中包含了两个主要信息:测量模式(MeasureSpec mode)和测量大小(MeasureSpec size)。
MeasureSpec 的测量模式有三种:EXACTLY、AT_MOST 和 UNSPECIFIED。EXACTLY 表示视图的大小已经确定,是一个精确的值;AT_MOST 表示视图的大小不能超过某个限定值,即视图大小有一个上限;UNSPECIFIED 表示视图的大小没有限制,可以是任何大小。MeasureSpec 的测量大小是一个 int 值,表示视图的宽度或高度。测量大小的计算依赖于测量模式。在 EXACTLY 模式下,测量大小就是视图的精确宽度或高度值;在 AT_MOST 模式下,测量大小是视图的最大宽度或高度值;在 UNSPECIFIED 模式下,测量大小可以是任意值。在自定义视图中,widthMeasureSpec 和 heightMeasureSpec 是由父容器传递给子视图的。子视图需要根据这两个参数来确定自己的宽度和高度。在视图的 onMeasure 方法中,可以通过调用 resolveSize 方法来根据 widthMeasureSpec 和 heightMeasureSpec 计算出视图的实际宽度和高度。下面是一个简单的自定义视图的案例代码,用于演示 widthMeasureSpec 和 heightMeasureSpec 的用法:javapublic class MyView extends View { public MyView(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int width, height; if (widthMode == MeasureSpec.EXACTLY) { width = widthSize; } else if (widthMode == MeasureSpec.AT_MOST) { width = Math.min(widthSize, 200); // 最大宽度为 200 } else { width = 200; // 默认宽度为 200 } if (heightMode == MeasureSpec.EXACTLY) { height = heightSize; } else if (heightMode == MeasureSpec.AT_MOST) { height = Math.min(heightSize, 200); // 最大高度为 200 } else { height = 200; // 默认高度为 200 } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { // 绘制视图内容 }}在上述代码中,onMeasure 方法中首先通过 MeasureSpec.getMode 和 MeasureSpec.getSize 方法获取 widthMeasureSpec 和 heightMeasureSpec 的测量模式和测量大小。然后根据不同的测量模式计算出视图的实际宽度和高度,并通过 setMeasuredDimension 方法设置视图的大小。使用 resolveSize 方法在自定义视图中,我们也可以使用 resolveSize 方法来根据 widthMeasureSpec 和 heightMeasureSpec 计算出视图的实际宽度和高度。resolveSize 方法的实现如下:
javapublic static int resolveSize(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: result = Math.min(size, specSize); break; case MeasureSpec.EXACTLY: result = specSize; break; } return result;}使用 resolveSize 方法的示例代码如下:
javapublic class MyView extends View { public MyView(Context context) { super(context); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = resolveSize(200, widthMeasureSpec); int heightSize = resolveSize(200, heightMeasureSpec); setMeasuredDimension(widthSize, heightSize); } @Override protected void onDraw(Canvas canvas) { // 绘制视图内容 }}在上述代码中,onMeasure 方法中使用 resolveSize 方法将指定的宽度和高度转换为实际的宽度和高度,并通过 setMeasuredDimension 方法设置视图的大小。这样就可以根据需要灵活地计算视图的宽度和高度。