自定义FlowGroup继承ViewGroup,通过实现onMeasure和onLayout方法,实现子控件的自动换行
package com.shilian.yibo.view;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
/**
* 流式布局的viewgroup
* Created by Burn on 2017/4/24.
*/
public class FlowGroup extends ViewGroup {
/**
* 构造方法
* */
public FlowGroup(Context context) {
super(context);
}
public FlowGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FlowGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public FlowGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
/**
* 重写onMeasure方法,计算viewgroup的尺寸,保存子控件数据
* */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取FlowGroup的模式和尺寸
int sizeWidth=MeasureSpec.getSize(widthMeasureSpec);
int sizeHeight=MeasureSpec.getSize(heightMeasureSpec);
int modeWidth=MeasureSpec.getMode(widthMeasureSpec);
int modeHeight=MeasureSpec.getMode(heightMeasureSpec);
int width=0;//总宽
int height=0;//总高
int lineWidth=0;//行宽
int lineHeight=0;//行高
//遍历子控件获取数据
int mCount=getChildCount();
for (int i=0;i<mCount;i++){
View child=getChildAt(i);
measureChild(child,widthMeasureSpec,heightMeasureSpec);
MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int childWidth=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
int childHeight=child.getMeasuredHeight()+lp.topMargin+lp.bottomMargin;
if (lineWidth+childWidth<=sizeWidth){
lineWidth+=childWidth;
lineHeight=Math.max(lineHeight,childHeight);
}else {
width=Math.max(width,lineWidth);
height+=lineHeight;
lineWidth=childWidth;
lineHeight=childHeight;
}
if (i==mCount-1){
width=Math.max(width,lineWidth);
height+=lineHeight;
}
}
setMeasuredDimension(((modeWidth==MeasureSpec.EXACTLY)?sizeWidth:width),((modeHeight==MeasureSpec.EXACTLY)?sizeHeight:height));
}
private List<List<View>> mAllViews = new ArrayList<List<View>>();
/**
* 记录每一行的最大高度
*/
private List<Integer> mLineHeight = new ArrayList<Integer>();
/**
* 重写onLayout方法,实现子控件布局
* */
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left=0;//控件左侧位置
int top=0;//控件上方位置
int lineWidth=0;//行宽
int lineHeight=0;//行高
int mCount=getChildCount();
for (int i=0;i<mCount;i++){
View child=getChildAt(i);
MarginLayoutParams lp= (MarginLayoutParams) child.getLayoutParams();
if (child.getVisibility()==View.GONE){
continue;
}
int childWidth=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
int childHeight=child.getMeasuredHeight()+lp.topMargin+lp.bottomMargin;
if (lineWidth+childWidth<=getWidth()){
lineWidth+=childWidth;
lineHeight=Math.max(lineHeight,childHeight);
}else {
left=0;
top+=lineHeight;
lineWidth=childWidth;
lineHeight=childHeight;
}
int lc=left+lp.leftMargin;
int tc=top+lp.topMargin;
int rc=lc+child.getMeasuredWidth();
int bc=tc+child.getMeasuredHeight();
child.layout(lc, tc, rc, bc);
left+=childWidth;
}
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(),attrs);
}
}