在很多的时候会用到流式布局,根据字面意思就是就像水流一样的布局,
水流到了一行的尽头就要重新开始,在布局中添加的控件会根据每个子孩子,
的宽高来布局,首先我们创建一个类,继承viewgroup,重写
onLayout方法(根据onMeasure测量的宽高,进行布局摆放)
onMeasure方法(用来测量子孩子的宽高)
public class LiuShi extends ViewGroup { public LiuShi(Context context) { super(context); } public LiuShi(Context context, AttributeSet attrs) { super(context, attrs,0); } public LiuShi(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //测量所有孩子的宽高 measureChildren(widthMeasureSpec,heightMeasureSpec); //最大的宽度,也就是FlowLayout父布局的宽度 int widthSize = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int width=0; int height=0; int lineWidth=0; int lineHeight=0; View childView; int childWidth=0; int childHeight=0; int totalHeight=0; for (int i = 0; i < getChildCount(); i++) { childView=getChildAt(i); childWidth=childView.getMeasuredWidth(); //换行width就是最大宽,只要又换行的情况出现,说明流式布局的宽度已经不够用了 if(childWidth>widthSize){ throw new IllegalArgumentException("报错"); } childHeight=childView.getMeasuredHeight(); if(lineWidth+childWidth>widthSize){ width=widthSize; totalHeight+=lineHeight; lineWidth=childWidth; lineHeight=childHeight; }else { //不换行 lineWidth+=childWidth; //当前行的高度 lineHeight=Math.max(lineHeight,childHeight); //假如只有一行,那测量的宽度就是当前行宽,如果又换行那就去最大宽 width=Math.max(width,lineWidth); } //当结束遍历的时候要加上最后一行的高度 if(i==getChildCount()-1){ totalHeight+=lineHeight; height=totalHeight; } } width=widthMode==MeasureSpec.EXACTLY?widthSize:width; height=heightMode==MeasureSpec.EXACTLY?height:height; //确定最终测量的宽高 setMeasuredDimension(width,height); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int lineWidth=0; int lineHeight=0; int totalHeight=0; View childView; int childWidth=0; int childHeight=0; for (int i = 0; i < getChildCount(); i++) { childView=getChildAt(i); childWidth=childView.getMeasuredWidth(); childHeight=childView.getMeasuredHeight(); if(lineWidth+childHeight>getMeasuredWidth()){ totalHeight+=childHeight; lineWidth=0; layoutChildView(childView,lineWidth,totalHeight,lineWidth+childWidth,totalHeight+childHeight); lineHeight=childHeight; lineWidth=childWidth; }else { layoutChildView(childView,lineWidth,totalHeight,lineWidth+childWidth,totalHeight+childHeight); lineWidth+=childWidth; lineHeight=Math.max(lineHeight,childHeight); } } } private void layoutChildView(View child, int l, int t, int r, int b) { child.layout(l,t,r,b); } }
流式布局的主要做法就是判断子孩子宽高,在换行与不换行进行判断,