一、自定义ViewGroup代码
自定义VIew的关键在于重写onMeasure和onDraw,而自定义ViewGroup的关键在于重写onLayout方法。
public class FlowLayout extends ViewGroup {
//存储每行由哪些控件
List<List<View>> lineViews = new ArrayList();
//存储每行的高度
List<Integer> heightArray = new ArrayList();
//防止多次onMeasure导致测量信息不准确
boolean isMeasure = true;
public FlowLayout(Context context) {
super(context);
}
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取父控件给我们的 参考宽高
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
//获取父控件给我们的参考模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//保存当前控件的总宽高
int childCountWidth = 0;
int childCountHieght = 0;
if(isMeasure){
//用于存储每行的宽高
int lineCountWidth = 0;
int lineMaxHeight = 0;
int childWidth = 0;
int childHeight = 0;
//存储每一行的控件
List<View> viewLine = new ArrayList<>();
int countChild = getChildCount();
for(int i=0;i<countChild;i++){
View view = getChildAt(i);
//测量子控件
measureChild(view,widthMeasureSpec,heightMeasureSpec);
MarginLayoutParams lp = (MarginLayoutParams) view.getLayoutParams();
childWidth = view.getMeasuredWidth() + lp.rightMargin + lp.leftMargin;
childHeight = view.getMeasuredHeight() + lp.bottomMargin + lp.topMargin;
if(lineCountWidth + childWidth > widthSize){
heightArray.add(lineMaxHeight);
//如果新加入的View后宽度大于父控件宽度,则将此子控件放到另一行,并且清空viewLine
lineViews.add(viewLine)