package com.example.liushibuju; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; /** * Created by DELL on 2018/6/8. */ public class FlowLayout extends ViewGroup { public FlowLayout(Context context) { super(context); } public FlowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onLayout(boolean b, int i, int i1, int i2, int i3) { int lineWidth = 0; int lineHeight = 0; int totalHeight = 0; View childView; int childWidth = 0; int childHeight = 0; MarginLayoutParams layoutParams; int leftMargin; int rightMargin; int topMargin; int bottomMargin; for (int j = 0; j < getChildCount(); j++) { childView = getChildAt(j); childWidth = childView.getMeasuredWidth(); childHeight = childView.getMeasuredHeight(); layoutParams = (MarginLayoutParams) childView.getLayoutParams(); leftMargin = layoutParams.leftMargin; rightMargin = layoutParams.rightMargin; topMargin = layoutParams.topMargin; bottomMargin = layoutParams.bottomMargin; if (lineWidth + childWidth + leftMargin + rightMargin > getMeasuredWidth() - getPaddingLeft() - getPaddingRight()) { //换行 totalHeight += childHeight + topMargin + bottomMargin; lineWidth = 0 + leftMargin; layoutChildView(childView, lineWidth + leftMargin, totalHeight + topMargin, lineWidth + childWidth + leftMargin, totalHeight + childHeight + topMargin); lineHeight = childHeight + topMargin + bottomMargin; lineWidth = childWidth + leftMargin + rightMargin; } else { //不换行 layoutChildView(childView, lineWidth + leftMargin, totalHeight + topMargin, lineWidth + childWidth + leftMargin, totalHeight + childHeight + topMargin); lineWidth += childWidth + leftMargin + rightMargin; lineHeight = Math.max(lineHeight, childHeight + topMargin + bottomMargin); } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //测量所有孩子的宽高 measureChildren(widthMeasureSpec, heightMeasureSpec); 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; int totalHeight = 0; int childWidth = 0; int childHeight = 0; View childView; MarginLayoutParams layoutParams; int leftMargin; int rightMargin; int topMargin; int bottomMargin; for (int i = 0; i < getChildCount(); i++) { childView = getChildAt(i); childWidth = childView.getMeasuredWidth(); childHeight = childView.getMeasuredHeight(); layoutParams = (MarginLayoutParams) childView.getLayoutParams(); leftMargin = layoutParams.leftMargin; rightMargin = layoutParams.rightMargin; topMargin = layoutParams.topMargin; bottomMargin = layoutParams.bottomMargin; if (childWidth + leftMargin + rightMargin > widthsize - getPaddingLeft() - getPaddingRight()) { throw new IllegalArgumentException("子view的宽度不能大于父布局的宽度"); } if (lineWidth + childWidth + leftMargin + rightMargin > widthsize - getPaddingLeft() - getPaddingRight()) { //换行 width = widthsize; totalHeight += lineHeight; lineWidth = childWidth + leftMargin + rightMargin; lineHeight = childHeight + topMargin + bottomMargin; } else { //不换行 lineWidth += childWidth + leftMargin + rightMargin; //比较当前行的高度 lineHeight = Math.max(lineHeight, childHeight + topMargin + bottomMargin); //比较当前宽度,如果没有换行那么宽度就是当前的行宽,否则就是最大宽 width = Math.max(width, lineWidth + getPaddingLeft() + getPaddingRight()); } //当结束遍历的时候要加上最后一行的高 if (i == getChildCount() - 1) { totalHeight += lineHeight; height = totalHeight; } } width = widthmode == MeasureSpec.EXACTLY ? widthsize : width; height = heightmode == MeasureSpec.EXACTLY ? heightsize : height + getPaddingTop() + getPaddingBottom(); setMeasuredDimension(width, height); } public void layoutChildView(View child, int l, int t, int r, int b) { //统一根据flowlayout设置的padding进行整体的平移 l += getPaddingLeft(); t += getPaddingTop(); r += getPaddingLeft(); b += getPaddingLeft(); child.layout(l, t, r, b); } @Override protected LayoutParams generateDefaultLayoutParams() { return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); } @Override protected LayoutParams generateLayoutParams(LayoutParams p) { return new MarginLayoutParams(p); } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } }