个人觉得,自定义ViewGroup容器,核心是要确定里面每个子view的位置,ViewGroup的测量可以挪用源码中的是三种模式即可,个人开发去计算每个子view的大小显得相对复杂,系统自带的几种布局方式已足够使用,布局容器的核心还是在于子view的位置,测量和绘制使用默认的即可。 import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.List; public class MyViewGroup extends ViewGroup { private Context mContext; private LayoutInflater layoutInflater; public MyViewGroup(Context context) { this(context,null); } public MyViewGroup(Context context, AttributeSet attrs) { this(context, attrs,0); } public MyViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; init(); } private void init() { layoutInflater = LayoutInflater.from(mContext); } public void setTextViews(List<String> strings){ List<String> content = strings; for (int i = 0; i < content.size(); i++) { TextView textView = (TextView) layoutInflater.inflate(R.layout.textview_child, this, false); textView.setText(content.get(i)); this.addView(textView); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); int left = getLeft()+getPaddingLeft(); int top = getTop()+getPaddingTop(); int right = getRight()-getPaddingRight(); int bottom = getBottom()-getPaddingBottom(); int lines = 0;//布局到第几行 for (int i = 0; i < childCount; i++) { View childAt = getChildAt(i); int childRight = left+ childAt.getMeasuredWidth(); int childBottom = top+childAt.getMeasuredHeight(); //换行 if (childRight> right){ lines++; left = getLeft()+getPaddingLeft(); childRight = left+childAt.getMeasuredWidth(); top = getTop()+getPaddingTop()+lines*childAt.getMeasuredHeight()+10*lines; childBottom = top+childAt.getMeasuredHeight(); } if (childBottom <= bottom){ //父容器的右上角作为layout的原点,所以需要减去父容器的起始值 childAt.layout(left-l,top-t,childRight-l,childBottom-t); left += childAt.getMeasuredWidth()+10; } } } //ViewGroup没有实现onMeasure方法 而是在各个实现类layout下面去实现这个测量方法,因为不同的layout布局特性不同 无法做到统一的标准 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // int measureWidth = 0; // int measureHeight = 0; // // int childCount = getChildCount();//ViewGroup中view的数量 // 1.测量所有子view // measureChildren(widthMeasureSpec,heightMeasureSpec);//测量所有的子view 内部包含对子view的循环 调用了measureChild() 2.合并所有子View的尺寸大小,得到最终ViewGroup父layout的测量值 开发者需要根据自己定制的layout的特性来得到合并后的父layout的测量宽高 // 3.存储测量后view的大小值。 // setMeasuredDimension(measureWidth,measureHeight); // super.onMeasure(widthMeasureSpec, heightMeasureSpec); //触发所有子View的onMeasure函数去测量宽高 measureChildren(widthMeasureSpec, heightMeasureSpec); //MeasureSpec封装了父View传递给子View的布局要求 super.onMeasure(widthMeasureSpec,heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } }