转载自: https://blog.csdn.net/sinat_31057219/article/details/80592171
自定义view如下:
public class MyView extends View {
private static final int DEFAULT_WIDTH = 100;
private static final int DEFAULT_HEIGHT = 100;
private Paint paint;
private Rect rect;
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
paint = new Paint();
paint.setColor(Color.parseColor("#ff0000"));
rect = new Rect(getPaddingLeft(), getPaddingTop(), 200, 200);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getProperSize(DEFAULT_WIDTH, widthMeasureSpec);
int height = getProperSize(DEFAULT_HEIGHT, heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int getProperSize(int defaultSize, int measureSpec) {
int result;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
result = defaultSize;
if (mode == MeasureSpec.AT_MOST) {
result = Math.min(result, size);
}
}
return result;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);//可省略
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(rect, paint);
}
}
onMeasure与onSizeChanged获取尺寸区别:
获取的尺寸单位均为px
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);//
int width = getWidth();
int height = getHeight();
int measuredHeight = getMeasuredHeight();
int measuredWidth = getMeasuredWidth();
//onMeasure中:
//Width = Height = 0
//当具体数据或match_parent时:
//measuredHeight的最后数值 = onSizeChanged中h = height = measuredHeight
//measuredWidth的最后数值 = onSizeChanged中w = width = measuredWidth
int suggestedMinimumWidth = getSuggestedMinimumWidth();
int suggestedMinimumHeight = getSuggestedMinimumHeight();
//等于xml中指定的min尺寸与背景图的min尺寸中较大值,否则为零
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);//空方法,可删
int width = getWidth();
int height = getHeight();
int measuredHeight = getMeasuredHeight();
int measuredWidth = getMeasuredWidth();
//onSizeChanged中
//w = width = measuredWidth
//h = height = measuredHeight
//oldw = onMeasure方法中getWidth()的最后数值
//oldh = onMeasure方法中getHeight()的最后数值
int suggestedMinimumWidth = getSuggestedMinimumWidth();
int suggestedMinimumHeight = getSuggestedMinimumHeight();
//等于xml中指定的min尺寸与背景图的min尺寸中较大值,否则为零
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);源码:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
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:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
可看出:
wrap_content和match_parent具有相同的效果,即填充父容器
getSuggestedMinimumWidth方法源码:
private int mMinWidth;
private int mMinHeight;
private Drawable mBackground;
protected int getSuggestedMinimumWidth() {
return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
}
protected int getSuggestedMinimumHeight() {
return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
}