例1. 缺少默认值 | 自己写的
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int finalWidth, finalHeight;
// 不明
finalWidth = getSuggestedMinimumWidth();
finalHeight = getSuggestedMinimumHeight();
if (widthMode == MeasureSpec.EXACTLY) {
finalWidth = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
int padding = getPaddingLeft() + getPaddingRight();
finalWidth += padding;
}
if (heightMode == MeasureSpec.EXACTLY) {
finalHeight = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
int padding = getPaddingTop() + getPaddingBottom();
finalHeight += padding;
}
setMeasuredDimension(finalWidth, finalHeight);
}
① 上面的例子中缺少默认值,所以高度为0
②
例2. 指定默认宽高 | 对第三种测量模式UNSPECIFIED的理解
@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);
解决的方法总结:
- 指定一个默认的内部宽高,例如本方法中的desiredWidth = 100。
- 判断当MeasureSpec的模式为AT_MOST(对应于wrap_content)时,设置结果为设置的值(最大为我们设置的值,如果小于设置值就设置为specSize)。
- 判断当MeasureSpec的模式为非AT_MOST时,直接设置为系统的测量值即可。
- 设置值没有特定的标准,以实际情况为准。
以上作者:Jinlin
链接:https://www.jianshu.com/p/95b98edda6ac
例3. 宽高默认值
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}
private int measureHeight(int measureSpec) {
int result = 0;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
result=75;
if (mode == MeasureSpec.AT_MOST) {
result = Math.min(result, size);
}
}
return result;
}
private int measureWidth(int measureSpec) {
int result = 0;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
result = 75;//根据自己的需要更改
if (mode == MeasureSpec.AT_MOST) {
result = Math.min(result, size);
}
}
return result;
}
①
②
③ UNSPECIFIED 这种模式不指定测量模式,view大小没有限制,想多大就多大。
版权声明:本文为CSDN博主「mxiaoyem」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mxiaoyem/article/details/51077054
另外(https://www.cnblogs.com/wjtaigwh/p/6600035.html)
如果我们的自定义控件在布局文件中,只需要设置指定的具体宽高,或者MATCH_PARENT 的情况,我们可以不用重写onMeasure方法。
但如果自定义控件需要设置包裹内容WRAP_CONTENT ,我们需要重写onMeasure方法,为控件设置需要的尺寸;默认情况下WRAP_CONTENT 的处理也将填充整个父控件。
onMeasure方法最后需要调用setMeasuredDimension方法来保存测量的宽高值。
题外话
例1中,发现在onMeasure()里最终确定宽高时调用setMeasuredDimension()。
在onSizeChanged()中getMeasuredWidth()/getMeasuredHeight(),get方法得到的数值应该就是onMeasure()中set方法确定的。

// 点进去看看源码就知道了


网友评论