测量,赋值,绘制
- 测量:父view调用子view的onMeasure()方法,首先看子view是一个view还是viewgroup, 如果子view是一个view,直接调用它的onMeasure方法去测量,并把测量结果返回给父view。如果子view是一个viewgroup, 分别测量每个子view,保存每个子view的尺寸,并且计算并保存自己的尺寸。
1.测量已有view的尺寸
public class MyImageView extends android.support.v7.widget.AppCompatImageView {
public MyImageView(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
if (width > height) {
width = height;
} else {
height = width;
}
setMeasuredDimension(width, height);
}
}
2.测量自定义view的尺寸
public class CustomView extends ViewGroup {
public CustomView(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getMeasuredWidth();
int height = getMeasuredHeight();
width = resolveSize(width, widthMeasureSpec);
height = resolveSize(height, heightMeasureSpec);
setMeasuredDimension(width, height);
}
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);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
}
3.测量与布局自定义view
public class MyView extends ViewGroup {
public MyView(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int viewCount = getChildCount();
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
for (int i = 0; i < viewCount; i++) {
View view = getChildAt(i);
LayoutParams lp = view.getLayoutParams();
int childMeasureSpec;
switch (lp.width) {
case LayoutParams.MATCH_PARENT:
if(widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST){
childMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize - 10, MeasureSpec.EXACTLY);
}else {
childMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
break;
case LayoutParams.WRAP_CONTENT:
if(widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST){
childMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize- 10 , MeasureSpec.AT_MOST);
}else{
childMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
default:
childMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
break;
}
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int viewCount = getChildCount();
for(int i=0; i<viewCount; i++){
View view = getChildAt(i);
view.layout(getLeft(), getTop(), getRight(), getBottom());
}
}
}