在自定义控件中,我们经需要测量空间大小,这时会遇到onMeasure这个方法,在这个方法中遇到 widthMeasureSpec和heightMeasureSpec。
这两个参数均为int类型,转为二进制为32位,他们既表示宽高的模式和大小。用下图表示
对应安卓源码中
/**
* Measure specification mode: The parent has not imposed any constraint
* on the child. It can be whatever size it wants.
*/
public static final int UNSPECIFIED = 0 << MODE_SHIFT;
/**
* Measure specification mode: The parent has determined an exact size
* for the child. The child is going to be given those bounds regardless
* of how big it wants to be.
*/
public static final int EXACTLY = 1 << MODE_SHIFT;
/**
* Measure specification mode: The child can be as large as it wants up
* to the specified size.
*/
public static final int AT_MOST = 2 << MODE_SHIFT;
在我们自己的项目中我们可以对宽高作如下处理
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(measureSize(widthMeasureSpec), measureSize(heightMeasureSpec));
}
public int measureSize(int measureSpec) {
//获取模式
int viewMode = MeasureSpec.getMode(measureSpec);
//获取大小
int viewSize = MeasureSpec.getSize(measureSpec);
if (viewMode == MeasureSpec.AT_MOST) {
//设为wrap_content 最大不会超过父组件
return MeasureSpec.makeMeasureSpec(2 << 10, viewMode);//表示大小自适应,但是最大长度不会超过80<<3==640
} else if (viewMode == MeasureSpec.EXACTLY) {
//设为match_parent或者设置精确值例如50dp
return measureSpec;
} else {
//MeasureSpec.UNSPECIFIED 未指定模式,没有确定大小,随便这种情况基本不多
return measureSpec;
}
}
MeasureSpec.getMode(measureSpec)获取她的模式
MeasureSpec.getSize(measureSpec)获取它的长度
MeasureSpec.makeMeasureSpec(2 << 10, viewMode)设置模式和大小得到一个新的MeasureSpec,用于该控件