1、继承自View的自定义View为什么要重写onMeasure方法:
View.java中的onMeasure方法如下:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
/**
* Utility to return a default size. Uses the supplied size if the
* MeasureSpec imposed no constraints. Will get larger if allowed
* by the MeasureSpec.
*
* @param size Default size for this view
* @param measureSpec Constraints imposed by the parent 即父布局的大小
* @return The size this view should be.
*/
public static int getDefaultSize(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://wrap_content和match_parent都执行result=specSize,即填满父布局
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
从源码来看,继承自View的自定义View的宽高总是填满父布局,导致wrap_content失效。但android:width="100dp"是生效的。
所以为了使wrap_content生效,就需要重写onMeasure方法,计算最小宽高。
比如:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d("SIZES", "called onMeasure()");
int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
int minh = getSuggestedMinimumHeight() + getPaddingBottom() + getPaddingTop();
setMeasuredDimension(
resolveSize(minw, widthMeasureSpec),
resolveSize(minh, heightMeasureSpec));
}
但对于继承自View的自定义View来说,使用wrap_content好像意义不大,一般都用match_parent或100dp之类。
如果有需要,也可以重写getSuggestedMinimunWidth和resolveSize方法。一般没必要。如果觉得getSuggestedMinimunWidth总是返回0,那就往下看↓
另外,getSuggestedMinimumWidth的值如果设置了background那就返回background的最小width;如果没有backgroud,则取mMinWidth值。
protected int getSuggestedMinimumWidth() {
return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
}
case R.styleable.View_minWidth:
mMinWidth = a.getDimensionPixelSize(attr, 0); //如果没有设置style属性View_minWidth,那么其默认值为0.
break;
public void setMinimumWidth(int minWidth) {//-------------------除了设置style属性View_minWidth,也可以调用setMinimumWidth方法。
mMinWidth = minWidth;
requestLayout();
}