自定義view
測量,賦值,繪製
-
測量:父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()); } } }