package com.bigfat.viewpagerinscrollviewdemo;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import java.util.ArrayList;
import java.util.List;
public class FlowLayout extends FrameLayout {
public static final String TAG = "FlowLayout";
public final int LAYOUT_DIRECTION_LTR = 0;
public final int LAYOUT_DIRECTION_RTL = 1;
private int layoutDirection;
/**
* 用于一行一行的存储所有的View
*/
private List<List<View>> mAllViews = new ArrayList<>();
/**
* 每一行的高度
*/
private List<Integer> mLineHeight = new ArrayList<>();
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);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout);
this.layoutDirection = a.getInt(R.styleable.FlowLayout_layout_direction, LAYOUT_DIRECTION_LTR);
a.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//MeasureSpec.EXACTLY测量模式
// int sizeWith = MeasureSpec.getSize(widthMeasureSpec);
// int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
// int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
// int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
//// Log.i(TAG, "sizeWith--->" + String.valueOf(sizeWith));
//// Log.i(TAG, "sizeHeight--->" + String.valueOf(sizeHeight));
//// Log.i(TAG, String.valueOf(modeWidth == MeasureSpec.EXACTLY));
//
// //MeasureSpec.AT_MOST测量模式,即宽/高设置为wrap_content时
// int width = 0;
// int height = 0;
// //记录每一行的宽度与高度
// int lineWidth = 0;
// int lineHeight = 0;
// //得到内部元素的个数
// int cCount = getChildCount();
// for (int i = 0; i < cCount; i++) {
// //得到子View
// View child = getChildAt(i);
// if (child.getVisibility() == GONE) {
// continue;
// }
// //测量子View
// measureChild(child, widthMeasureSpec, heightMeasureSpec);
// //得到LayoutParams,这里之所以是MarginLayoutParams,是因为在generateLayoutParams方法中返回的是MarginLayoutParams
// MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
// //子View占据的宽度
// int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
// //子View占据的高度
// int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
// //如果该行已有控件占满一行,则换行
// if (lineWidth + childWidth > sizeWith - getPaddingLeft() - getPaddingRight()) {
// //取最宽的一行的宽度作为FlowLayout的宽度
// width = Math.max(width, lineWidth);
// //高度叠加
// height += lineHeight;
//
// //重置新的一行的行宽,行高
// lineWidth = childWidth;
// lineHeight = childHeight;
// } else {//不换行
// //宽度叠加
// lineWidth += childWidth;
// //高度取最大值
// lineHeight = Math.max(lineHeight, childHeight);
// }
// //如果是最后一个控件,要记录行宽与行高,因为不论换不换行,都会漏记/不对比最后一个控件的宽高
// if (i == cCount - 1) {
// width = Math.max(lineWidth, childWidth);
// height += lineHeight;
// }
// }
// //根据测量模式设置宽高
// setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWith : width + getPaddingLeft() + getPaddingRight(),
// modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height + getPaddingTop() + getPaddingBottom());
if (getChildCount() > 0) {
final View child = getChildAt(0);
int height = getMeasuredHeight();
if (child.getMeasuredHeight() < height) {
final FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) child.getLayoutParams();
int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
getPaddingLeft() + getPaddingRight(), lp.width);
height -= getPaddingTop();
height -= getPaddingBottom();
int childHeightMeasureSpec =
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
}
}
@Override
protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
LayoutParams lp = (LayoutParams) child.getLayoutParams();
int childWidthMeasureSpec;
int childHeightMeasureSpec;
childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, getPaddingLeft()
+ getPaddingRight(), lp.width);
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
@Override
protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin
+ widthUsed, lp.width);
final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
lp.topMargin + lp.bottomMargin, MeasureSpec.UNSPECIFIED);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed,l,t,r,b);
// //onLayout可能会被多次调用,所以先清空List
// mAllViews.clear();
// mLineHeight.clear();
//
// int width = getWidth();
// int cCount = getChildCount();
// //每行子View
// List<View> lineViews = new ArrayList<>();
// //每行宽高
// int lineWidth = 0;
// int lineHeight = 0;
// //遍历子View
// for (int i = 0; i < cCount; i++) {
// //取得子View,及相关属性
// View child = getChildAt(i);
// if (child.getVisibility() == GONE) {
// continue;
// }
// int childWidth = child.getMeasuredWidth();
// int childHeight = child.getMeasuredHeight();
// MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
// //如果需要换行
// if (lineWidth + childWidth + lp.leftMargin + lp.rightMargin > width - getPaddingLeft() - getPaddingRight()) {
// //记录当前行数据
// mLineHeight.add(lineHeight);
// mAllViews.add(lineViews);
// //重置行数据
// lineWidth = 0;
// lineHeight = 0;
// lineViews = new ArrayList<>();
// }
// //计算当前行宽高
// lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
// lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin);
// //添加当前子View至当前行子View列表中
// lineViews.add(child);
// }
// //记录最后一行数据
// mLineHeight.add(lineHeight);
// mAllViews.add(lineViews);
//
//
// int top = getPaddingTop();
// //行数
// int lineNum = mAllViews.size();
// //遍历每行
// for (int i = 0; i < lineNum; i++) {
// int left = getPaddingLeft();
// int right = getMeasuredWidth() - getPaddingRight();
// //获取当前行所有View
// lineViews = mAllViews.get(i);
// lineHeight = mLineHeight.get(i);
// //遍历当前行View
// for (int j = 0; j < lineViews.size(); j++) {
// View child = lineViews.get(j);
// //判断View显示状态
// if (child.getVisibility() == View.GONE) {
// continue;
// }
// MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
// //设置子View的位置
// int cLeft = 0;
// int cTop = 0;
// int cRight = 0;
// int cBottom = 0;
// cTop = top + lp.topMargin;
// cBottom = cTop + child.getMeasuredHeight();
// switch (layoutDirection) {
// case LAYOUT_DIRECTION_LTR://从左向右
// cLeft = left + lp.leftMargin;
// cRight = cLeft + child.getMeasuredWidth();
//
// left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
// break;
//
// case LAYOUT_DIRECTION_RTL://从右向左
// cRight = right - lp.rightMargin;
// cLeft = cRight - child.getMeasuredWidth();
//
// right -= child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
// break;
// }
// //布局
// child.layout(cLeft, cTop, cRight, cBottom);
// }
// top += lineHeight;
// }
}
// 继承自margin,支持子视图android:layout_margin属性
public static class LayoutParams extends MarginLayoutParams {
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
public LayoutParams(MarginLayoutParams source) {
super(source);
}
}
}