FlowLayout.java package com.shuijiaosuidao.user.v.view;import android.content.Context;import android.content.res.TypedArray;import android.database.DataSetObserver;import android.util.AttributeSet;import android.view.View;import android.vie
package com.shuijiaosuidao.user.v.view; import android.content.Context; import android.content.res.TypedArray; import android.database.DataSetObserver; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import com.shuijiaosuidao.user.R; /** * @author: xiaolijuan * @description: 流式布局-标签流容器 * @projectName: FlowLayoutDome * @date: 2016-06-16 * @time: 16:21 */ public class FlowLayout extends ViewGroup { /** * 每个item纵向间距 */ private int mVerticalSpacing; /** * 每个item横向间距 */ private int mHorizontalSpacing; private BaseAdapter mAdapter; private OnItemClickListener mListener; private DataChangeObserver mObserver; public FlowLayout(Context context) { this(context, null); } public FlowLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FlowLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); /** * 获得我们所定义的自定义样式属性 */ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.FlowLayout, defStyle, 0); for (int i = 0; i < a.getIndexCount(); i++) { int attr = a.getIndex(i); switch (attr) { case R.styleable.FlowLayout_verticalSpacing: mVerticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_verticalSpacing, 5); break; case R.styleable.FlowLayout_horizontalSpacing: mHorizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_horizontalSpacing, 10); break; } } a.recycle(); } //wxm:设置子View的间距 public void setSpacing(int verticalSpacing, int horizontalSpacing) { mVerticalSpacing = verticalSpacing; mHorizontalSpacing = horizontalSpacing; } /** * 负责设置子控件的测量模式和大小 根据所有子控件设置自己的宽和高 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int widthMode = MeasureSpec.getMode(widthMeasureSpec); final int heightMode = MeasureSpec.getMode(heightMeasureSpec); final int widthSize = MeasureSpec.getSize(widthMeasureSpec); final int heightSize = MeasureSpec.getSize(heightMeasureSpec); measureChildren(widthMeasureSpec, heightMeasureSpec); int width = 0; int height = 0; int row = 0; // The row counter. int rowWidth = 0; // Calc the current row width. int rowMaxHeight = 0; // Calc the max tag height, in current row. final int count = getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); final int childWidth = child.getMeasuredWidth(); final int childHeight = child.getMeasuredHeight(); if (child.getVisibility() != GONE) { rowWidth += childWidth; if (rowWidth > widthSize) { // Next line. rowWidth = childWidth; // The next row width. height += rowMaxHeight + mVerticalSpacing; rowMaxHeight = childHeight; // The next row max height. row++; } else { // This line. rowMaxHeight = Math.max(rowMaxHeight, childHeight); } rowWidth += mHorizontalSpacing; } } // Account for the last row height. height += rowMaxHeight; // Account for the padding too. height += getPaddingTop() + getPaddingBottom(); // If the tags grouped in one row, set the width to wrap the tags. if (row == 0) { width = rowWidth; width += getPaddingLeft() + getPaddingRight(); } else {// If the tags grouped exceed one line, set the width to match the parent. width = widthSize; } setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width, heightMode == MeasureSpec.EXACTLY ? heightSize : height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int parentLeft = getPaddingLeft(); final int parentRight = r - l - getPaddingRight(); final int parentTop = getPaddingTop(); final int parentBottom = b - t - getPaddingBottom(); int childLeft = parentLeft; int childTop = parentTop; int rowMaxHeight = 0; final int count = getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); final int width = child.getMeasuredWidth(); final int height = child.getMeasuredHeight(); if (child.getVisibility() != GONE) { if (childLeft + width > parentRight) { // Next line childLeft = parentLeft; childTop += rowMaxHeight + mVerticalSpacing; rowMaxHeight = height; } else { rowMaxHeight = Math.max(rowMaxHeight, height); } child.layout(childLeft, childTop, childLeft + width, childTop + height); childLeft += width + mHorizontalSpacing; } } } private void drawLayout() { if (mAdapter == null || mAdapter.getCount() == 0) { return; } removeAllViews(); for (int i = 0; i < mAdapter.getCount(); i++) { View view = mAdapter.getView(i, null, null); final int position = i; view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mListener != null) { mListener.itemClick(position); } } }); addView(view); } } public void setAdapter(BaseAdapter adapter) { if(mAdapter!=null && mObserver!=null){ mAdapter.unregisterDataSetObserver(mObserver); } mAdapter = adapter; if(mAdapter!=null){ if (mObserver == null) { mObserver = new DataChangeObserver(); } mAdapter.registerDataSetObserver(mObserver); drawLayout(); } } public void setItemClickListener(OnItemClickListener mListener) { this.mListener = mListener; } public interface OnItemClickListener { void itemClick(int position); } class DataChangeObserver extends DataSetObserver { @Override public void onChanged() { drawLayout(); } @Override public void onInvalidated() { super.onInvalidated(); } } }