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();
}
}
}
