package cn.mutils.app.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import cn.mutils.app.R;
import cn.mutils.core.event.IListener;
@SuppressWarnings({"UnnecessaryInterfaceModifier", "unused"})
public class FlowLayout extends ViewGroup {
public static interface OnLinesChangeListener extends IListener {
void onChanged(FlowLayout v, int lines);
}
protected int mHorizontalGap;
protected int mVerticalGap;
protected int mMaxLines = -1;
protected int mMeasuredLines;
protected OnLinesChangeListener mOnLinesChangeListener;
public FlowLayout(Context context) {
super(context);
init(context, null);
}
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
protected void init(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);
mHorizontalGap = typedArray.getDimensionPixelSize(R.styleable.FlowLayout_android_horizontalGap, 10);
mVerticalGap = typedArray.getDimensionPixelSize(R.styleable.FlowLayout_android_verticalGap, 10);
mMaxLines = typedArray.getInt(R.styleable.FlowLayout_android_maxLines, -1);
typedArray.recycle();
}
}
public void setOnLinesChangeListener(OnLinesChangeListener listener) {
mOnLinesChangeListener = listener;
}
public int getMaxLines() {
return mMaxLines;
}
public void setMaxLines(int maxLines) {
if (mMaxLines == maxLines) {
return;
}
mMaxLines = maxLines;
this.requestLayout();
this.invalidate();
}
public int getMeasuredLines() {
return mMeasuredLines;
}
public void setMeasuredLines(int measuredLines) {
mMeasuredLines = measuredLines;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
int h = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
int childHeightMeasureSpec;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.AT_MOST);
} else {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
int x = getPaddingLeft();
int y = getPaddingTop();
int rowHeight = 0;
int maxHeight = 0;
int lines = 1;
boolean linesInvalidate = false;
for (int i = 0, size = this.getChildCount(); i < size; i++) {
View child = getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
if (linesInvalidate) {
linesInvalidate = false;
rowHeight = 0;
}
child.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.AT_MOST), childHeightMeasureSpec);
rowHeight = Math.max(rowHeight, child.getMeasuredHeight() + mVerticalGap);
if (x + child.getMeasuredWidth() > w) {
if (x > getPaddingLeft()) {
x = getPaddingLeft();
y += rowHeight;
if (lines == mMaxLines) {
maxHeight = y;
}
lines++;
linesInvalidate = true;
}
}
LayoutParams lp = (LayoutParams) child.getLayoutParams();
lp.mX = x;
lp.mY = y;
x += child.getMeasuredWidth() + mHorizontalGap;
}
if (maxHeight != 0) {// 固定高度
h = maxHeight;
} else {
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
h = y + rowHeight;
} else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
if (y + rowHeight < h) {
h = y + rowHeight;
}
}
}
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), h + getPaddingBottom());
if (mMeasuredLines != lines) {
mMeasuredLines = lines;
if (mOnLinesChangeListener != null) {
mOnLinesChangeListener.onChanged(this, lines);
}
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = this.getChildCount() - 1; i >= 0; i--) {
View child = this.getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
LayoutParams lp = (LayoutParams) child.getLayoutParams();
child.layout(lp.mX, lp.mY, lp.mX + child.getMeasuredWidth(), lp.mY + child.getMeasuredHeight());
}
}
@Override
protected boolean checkLayoutParams(android.view.ViewGroup.LayoutParams p) {
return p != null && (p instanceof LayoutParams);
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
@Override
protected LayoutParams generateLayoutParams(android.view.ViewGroup.LayoutParams p) {
return new LayoutParams(p.width, p.height);
}
public static class LayoutParams extends ViewGroup.LayoutParams {
protected int mX;
protected int mY;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(LayoutParams source) {
super(source);
}
}
}