问题描述
Android系统在绘制View前,必须对View进行测量,即告诉系统该画一个多大的View。这个过程在onMeasure()方法中进行。
MeasureSpec类
Android系统提供了一个设计了一个短小精悍却功能强大的类--MeasureSpec类,通过它们来帮助我们测量View。
MeasureSpec是一个32位的int值,其中高2位为测量模式,低30位为测量的大小。
测量模式分为三种:
- EXACTLY
精确模式,当layout_width属性或layout_height属性指定为具体数值时或者指定match_parent属性时(占据父View的大小),此时系统使用EXACTLY模式。
- AT_MOST
最大值模式,当layout_width属性或layout_height属性指定为wrap_content时,即控件大小随着控件的子空间或内容的变化而变化,此时只要尺寸不超过父控件允许的最大尺寸。
- UNSPECIFIED
不知道大小测量模式,View想多大就多大,在绘制自定义View时才会使用。
View类默认的onMeasure()置支持EXACTLY模式,若使用自定义控件的时候不重写onMeasure()方法的话,就只能使用EXACTLY模式,此时支持指定具体宽高度值和match_parent属性;若使得自定义View支持wrap_content属性,必须重写onMeasure()方法指定wrap_content时的大小。
onMeasure()实现
系统最终调用setMeasureDimension()方法将测量后的宽高值设置进去,从而,重写的onMeasure()方法的主要工作为将测量的宽高作为参数设置给setMeasureDimension()方法。protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)); }
自定义测量值实现
如下代码为测量View宽度值代码(没有效果)
private int measureWidth(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if(specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = 200; if(specMode == MeasureSpec.AT_MOST) { result = Math.min(result, measureSpec); } } return result; }可以用android.View.View中的resolveSize(···,···)方法代替如上代码。resolveSize()方法调用resolveSizeAndState(···,···,···)方法,resolveSizeAndState()方法实现如下:
上下两份代码区别主要为,第一份代码测量值只有size,第二份代码测量值为size + mode。public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) { final int specMode = MeasureSpec.getMode(measureSpec); final int specSize = MeasureSpec.getSize(measureSpec); final int result; switch (specMode) { case MeasureSpec.AT_MOST: if (specSize < size) { result = specSize | MEASURED_STATE_TOO_SMALL; } else { result = size; } break; case MeasureSpec.EXACTLY: result = specSize; break; case MeasureSpec.UNSPECIFIED: default: result = size; } return result | (childMeasuredState & MEASURED_STATE_MASK); }
本文详细介绍了Android中View的尺寸计算方法onMeasure(),讲解了MeasureSpec类的三种测量模式:EXACTLY、AT_MOST和UNSPECIFIED,并探讨了如何在自定义View时实现wrap_content的效果,提供了onMeasure()方法的实现示例。
3009

被折叠的 条评论
为什么被折叠?



