FlowLayout,通过自定义ViewGroup来实现,主要重写的onMeasure()和onLayout()方法;onMeasure()作用是计算自定义ViewGroup中控件的大小,从而确定自定义布局的with和height。onLayout()作用是对自定义ViewGroupz中的控件进行定位。
效果图:
FlowLayout.java:
public class FlowLayout extends ViewGroup { public FlowLayout(Context context) { this(context, null); } 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 onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int layoutWithSize = MeasureSpec.getSize(widthMeasureSpec); int layoutWithMode = MeasureSpec.getMode(widthMeasureSpec); int layoutHeightSize = MeasureSpec.getSize(heightMeasureSpec); int layoutHeightMode = MeasureSpec.getMode(heightMeasureSpec); int layoutWith = 0; int layoutHeight = 0; int lineWith = 0; int lineHeight = 0; int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec); MarginLayoutParams marginLayoutParams = (MarginLayoutParams) getChildAt(i).getLayoutParams(); int childWith = getChildAt(i).getMeasuredWidth() + marginLayoutParams.rightMargin + marginLayoutParams.leftMargin; int childHeight = getChildAt(i).getMeasuredHeight() + marginLayoutParams.topMargin + marginLayoutParams.bottomMargin; if (lineWith + childWith > layoutWithSize-getPaddingLeft()-getPaddingRight()) { layoutWith = Math.max(layoutWith, lineWith); lineWith = childWith; layoutHeight += lineHeight; lineHeight = childHeight; } else { lineWith += childWith; lineHeight = Math.max(lineHeight, childHeight); } if (i == childCount - 1) { layoutHeight += lineHeight; layoutWith = Math.max(layoutWith, childWith); } } Log.e("layoutHeight", layoutHeight + ""); Log.e("layoutWith", layoutWith + ""); Log.e("layoutWithSize", layoutWithSize + ""); setMeasuredDimension(layoutWithMode == MeasureSpec.EXACTLY ? layoutWithSize : layoutWith+getPaddingLeft()+getPaddingRight(), layoutHeightMode == MeasureSpec.EXACTLY ? layoutHeightSize : layoutHeight+getPaddingTop()+getPaddingBottom()); } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } //存放每行的高 private List<Integer> lineHeightList = new ArrayList<>(); //存放每行view的list的list private List<List<View>> allViews= new ArrayList<>(); @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { lineHeightList.clear(); allViews.clear(); int lineHeght = 0; int lineWith = 0; List<View> lineViews = new ArrayList<>(); for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); MarginLayoutParams marginLayoutParams = (MarginLayoutParams) child.getLayoutParams(); int childHeight = child.getMeasuredHeight(); int childWith = child.getMeasuredWidth(); if (lineWith + childWith + marginLayoutParams.leftMargin + marginLayoutParams.rightMargin > getWidth()-getPaddingLeft()-getPaddingRight()) { lineHeightList.add(lineHeght); allViews.add(lineViews); lineViews = new ArrayList<>(); lineWith = 0; lineHeght = childHeight + marginLayoutParams.topMargin + marginLayoutParams.bottomMargin; } lineWith += childWith + marginLayoutParams.leftMargin + marginLayoutParams.rightMargin; lineHeght = Math.max(lineHeght, childHeight + marginLayoutParams.topMargin + marginLayoutParams.bottomMargin); lineViews.add(child); } lineHeightList.add(lineHeght); allViews.add(lineViews); int lineNum = allViews.size(); int left=getPaddingLeft(); int top=getPaddingTop(); for (int i = 0; i < lineNum; i++) { // 当前行的所有的View lineViews = allViews.get(i); lineHeght = lineHeightList.get(i); for (int j = 0; j < lineViews.size(); j++) { View child = lineViews.get(j); // 判断child的状态 if (child.getVisibility() == View.GONE) { continue; } MarginLayoutParams lp = (MarginLayoutParams) child .getLayoutParams(); int lc = left + lp.leftMargin; int tc = top + lp.topMargin; int rc = lc + child.getMeasuredWidth(); int bc = tc + child.getMeasuredHeight(); // 为子View进行布局 child.layout(lc, tc, rc, bc); left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; } left = getPaddingLeft(); top += lineHeght ; } }