自己写的DEMO,参照了http://blog.csdn.net/a396901990/article/details/36475213,写了一个viewgroup为了便与记忆,打印了一些参数,先试XML
<?xml version="1.0" encoding="utf-8"?> <com.example.luoliang.measuredemo.MyViewGroup xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:background="#00ff00" tools:context="com.example.luoliang.measuredemo.MainActivity"> <Button android:id="@+id/tv" android:layout_width="120dp" android:layout_height="160dp" android:padding="10dp" android:layout_margin="30dp" android:background="#ff0000" android:textColor="#ffffff" android:text="Hello World!" /> </com.example.luoliang.measuredemo.MyViewGroup>
public class MyViewGroup extends ViewGroup { private static final String TAG = MyViewGroup.class.getSimpleName() ; private Context ctx ; private AttributeSet attrs ; public MyViewGroup(Context context) { this(context,null); // init(); } public MyViewGroup(Context context, AttributeSet attrs) { super(context, attrs); this.ctx = context; this.attrs = attrs; } @Override protected LayoutParams generateDefaultLayoutParams() { return new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(ctx,attrs); } @Override protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { return new LayoutParams(p); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); measureChildren(widthMeasureSpec,heightMeasureSpec); } @Override protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) { int mChildrenCount = getChildCount(); final int size = mChildrenCount; // measureChildren(widthMeasureSpec,heightMeasureSpec); for (int i=0;i<size;i++){ View view = this.getChildAt(i); MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams(); int width = lp.width; int height = lp.height; measureChild(view,widthMeasureSpec,heightMeasureSpec); // setMeasuredDimension(width,height); } // super.measureChildren(widthMeasureSpec, heightMeasureSpec); } // @Override // protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) { // super.measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec); // LayoutParams lp = child.getLayoutParams(); // final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,child.getPaddingLeft()+child.getPaddingRight(),lp.width); // final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,child.getPaddingTop()+child.getPaddingBottom(),lp.height); // child.measure(childWidthMeasureSpec,childHeightMeasureSpec); // } // public static int getChildMeasureSpec(int spec,int padding,int childDimension){ // int specMode = MeasureSpec.getMode(spec); // int specSize = MeasureSpec.getSize(spec); // int size = Math.max(0,specSize-padding);//父view建议子view用的值,但子view不一定用 // //子view想要的实际大小和模式需要计算 // int resultSize = 0; // int resultMode = MeasureSpec.EXACTLY ; // switch(specMode){ // case MeasureSpec.EXACTLY: // if (childDimension>0){ // resultSize = childDimension; // resultMode = MeasureSpec.EXACTLY; // // }else if (childDimension==LayoutParams.MATCH_PARENT){ // resultSize = size; // resultMode = MeasureSpec.EXACTLY; // }else if(childDimension==LayoutParams.WRAP_CONTENT){ // resultSize = size; // resultMode = MeasureSpec.AT_MOST; // } // break; // case MeasureSpec.AT_MOST: // if (childDimension>0){ // resultSize = childDimension; // resultMode = MeasureSpec.EXACTLY; // // }else if (childDimension==LayoutParams.MATCH_PARENT){ // resultSize = size; // resultMode = MeasureSpec.AT_MOST; // }else if (childDimension==LayoutParams.WRAP_CONTENT){ // resultSize = size; // resultMode = MeasureSpec.AT_MOST; // } // break; // case MeasureSpec.UNSPECIFIED: // if (childDimension>0){ // resultSize = childDimension; // resultMode = MeasureSpec.EXACTLY; // // }else if (childDimension==LayoutParams.MATCH_PARENT){ // resultSize = 0; // resultMode = MeasureSpec.UNSPECIFIED; // }else if (childDimension==LayoutParams.WRAP_CONTENT){ // resultSize = 0; // resultMode = MeasureSpec.UNSPECIFIED; // } // break; // } // return MeasureSpec.makeMeasureSpec(resultSize,resultMode); // } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { for (int i=0;i<getChildCount();i++){ View child = getChildAt(i); MarginLayoutParams mPara = (MarginLayoutParams) child.getLayoutParams(); MarginLayoutParams mParentPara = (MarginLayoutParams) getLayoutParams(); int width = child.getMeasuredWidth(); int height = child.getMeasuredHeight(); int mLeft = (r-width)/2; int mTop = (r-height)/2; DisplayMetrics dm = new DisplayMetrics(); WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE); wm.getDefaultDisplay().getMetrics(dm); Log.d(TAG,"dm.density:"+dm.density+"child.getWidth():"+child.getWidth()+"child.getHeight():"+child.getHeight()+"child.getMeasuredWidth():"+child.getMeasuredWidth()+"child.getMeasuredHeight():"+child.getMeasuredHeight()+ "child.getPaddingLeft():"+child.getPaddingLeft()+"child.getPaddingTop():"+child.getPaddingTop()+"child.getPaddingRight():"+child.getPaddingRight()+"child.getPaddingBottom():"+child.getPaddingBottom()+ "child.getLeft():"+child.getLeft()+"child.getTop():"+child.getTop()+"child.getRight():"+child.getRight()+"child.getBottom():"+child.getBottom()+"mPara.topMargin:"+mPara.topMargin +"mPara.topMargin:"+mPara.topMargin+"mPara.rightMargin:"+mPara.rightMargin+"mPara.bottomMargin:"+mPara.bottomMargin+"mParentPara.leftMargin"+mParentPara.leftMargin +"mParentPara.topMargin"+mParentPara.topMargin+"mParentPara.rightMargin"+mParentPara.rightMargin+"mParentPara.bottomMargin"+mParentPara.bottomMargin); child.layout(child.getPaddingLeft()+mPara.leftMargin,child.getPaddingTop()+mPara.topMargin,width+child.getPaddingRight()+mPara.rightMargin,mPara.bottomMargin+height+child.getPaddingBottom()); // child.layout(0,0,width+child.getPaddingRight(),height+child.getPaddingBottom()); // child.layout(child.getLeft(),child.getTop(),child.getRight(),child.getBottom()); Log.d(TAG,"child.getWidth():"+child.getWidth()+"child.getHeight():"+child.getHeight()); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } }12-05 02:34:34.814 23743-23743/com.example.luoliang.measuredemo D/MyViewGroup: dm.density:2.0child.getWidth():0child.getHeight():0child.getMeasuredWidth():240child.getMeasuredHeight():320child.getPaddingLeft():20child.getPaddingTop():20child.getPaddingRight():20child.getPaddingBottom():20child.getLeft():0child.getTop():0child.getRight():0child.getBottom():0mPara.topMargin:60mPara.topMargin:60mPara.rightMargin:60mPara.bottomMargin:60mParentPara.leftMargin0mParentPara.topMargin0mParentPara.rightMargin0mParentPara.bottomMargin0
12-05 02:34:34.814 23743-23743/com.example.luoliang.measuredemo D/MyViewGroup: child.getWidth():240child.getHeight():320
12-05 02:34:34.854 23743-23743/com.example.luoliang.measuredemo D/MyViewGroup: dm.density:2.0child.getWidth():240child.getHeight():320child.getMeasuredWidth():240child.getMeasuredHeight():320child.getPaddingLeft():20child.getPaddingTop():20child.getPaddingRight():20child.getPaddingBottom():20child.getLeft():80child.getTop():80child.getRight():320child.getBottom():400mPara.topMargin:60mPara.topMargin:60mPara.rightMargin:60mPara.bottomMargin:60mParentPara.leftMargin0mParentPara.topMargin0mParentPara.rightMargin0mParentPara.bottomMargin0
12-05 02:34:34.854 23743-23743/com.example.luoliang.measuredemo D/MyViewGroup: child.getWidth():240child.getHeight():320
child.layout(child.getPaddingLeft()+mPara.leftMargin,child.getPaddingTop()+mPara.topMargin,width+child.getPaddingRight()+mPara.rightMargin,mPara.bottomMargin+height+child.getPaddingBottom());注意就是这个方法里面一定要自己设置好,左上右下,左就是child的paddingLeft+child的leftMargin,上就是child的paddingtop+child的topMargin,右就是child的paddingright+child的rightMargin,下就是child的paddingBottom+child的bottomMargin,不然出来的位置不对,我开始也是不对,我也是通过打印后面那个log才知道的,
mParentPara这个在Log里没值,应该是在遍历子view,还没有到编译自己
可以把注释的measureChild的这个方法打开,用自己写的,其实跟系统实现的是一样的