
个人觉得,自定义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);
}
}