package com.applite.view;
import java.util.ArrayList;
import java.util.List;
import android.R.integer;
import android.content.Context;
import android.content.Intent;
import android.provider.LiveFolders;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
public class FlowLayout extends ViewGroup {
public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//
}
public FlowLayout(Context context, AttributeSet attrs) {
//调用三个构造函数方法
this(context,attrs,0);
}
public FlowLayout(Context context) {
//调用两个构造函数方法
this(context, null);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取ViewGroup实际的宽和高 涉及到MeasureSpec类的使用
//宽度
int sizeWidth=MeasureSpec.getSize(widthMeasureSpec);
//宽模式
int modeWidth=MeasureSpec.getMode(widthMeasureSpec);
//高度
int sizeHeight=MeasureSpec.getSize(heightMeasureSpec);
//高模式
int modeHeight=MeasureSpec.getMode(heightMeasureSpec);
//wrap_content
int width=0;
int height=0;
//记录每一行的宽度和高度
int lineWidth=0;
int lineHeight=0;
//得到ViewGroup内部子元素个数
int childCount=getChildCount();
for (int i = 0; i < childCount; i++) {
//根据索引获取子view
View child=getChildAt(i);
//测量子view的宽和高
measureChild(child, widthMeasureSpec, heightMeasureSpec);
//得到LayoutParams(为何 查看generateLayoutParams )
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 > sizeWidth-getPaddingLeft()-getPaddingRight())
{
//对比得到最大的宽度
width=Math.max(width, lineWidth);
//重置lineHeight
lineWidth=childWidth;
//记录行高
height+=lineHeight;
lineHeight=childHeight;
}
else//未换行
{
//叠加行宽
lineWidth+=childWidth;
//当前行最大的高度设置给行高
lineHeight=Math.max(height, childHeight);
}
//到达最后一个控件
if(i==childCount-1)
{
width=Math.max(lineWidth, width);
height+=lineHeight;
}
}
Log.e("Tag", "sizeWidth:"+sizeWidth);
Log.e("Tag", "sizeHeight:"+sizeHeight);
//wrap_content
setMeasuredDimension(
modeWidth==MeasureSpec.EXACTLY ? sizeWidth:width+getPaddingLeft()+getPaddingRight(),
modeHeight==MeasureSpec.EXACTLY? sizeHeight:height+getPaddingTop()+getPaddingBottom()
);
}
/*
* 存储所有的view
*/
private List<List<View>> mAllViews=new ArrayList<List<View>>();
/*
* 每一行的高度
* */
private List<Integer> mLineHeight=new ArrayList<Integer>();
//对每一个子view视图进行布局
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mAllViews.clear();
mLineHeight.clear();
//获取当前ViewGroup宽度
int width=getWidth();
int lineWidth=0;
int lineHeight=0;
List<View> lineViews=new ArrayList<View>();
int childCount=getChildCount();
for (int i = 0; i < childCount; i++) {
View child=getChildAt(i);
MarginLayoutParams lp= (MarginLayoutParams)child.getLayoutParams();
int childWidth=child.getMeasuredWidth();
int childHeight=child.getMeasuredHeight();
//如果需要换行 考虑flowlayout padding
if(childWidth + lineWidth + lp.leftMargin + lp.rightMargin>width - getPaddingLeft() - getPaddingRight())
{
//记录LineHeight
mLineHeight.add(lineHeight);
//记录当前行的Views
mAllViews.add(lineViews);
//重置行宽和行高
lineWidth=0;
lineHeight=childHeight+lp.topMargin+lp.bottomMargin;
lineViews=new ArrayList<View>();
}
lineWidth+=childWidth + lp.leftMargin + lp.rightMargin;
lineHeight=Math.max(lineHeight, childHeight+lp.topMargin+lp.bottomMargin);
lineViews.add(child);
}
mLineHeight.add(lineHeight);
mAllViews.add(lineViews);
//设置子view的位置
int left=getPaddingLeft();
int top=getPaddingTop();
int lineNum=mAllViews.size();
for (int i = 0; i < lineNum; i++) {
//当前行所有的view
lineViews=mAllViews.get(i);
lineHeight=mLineHeight.get(i);
for (int j = 0; j < lineViews.size(); j++) {
View child=lineViews.get(j);
//判断child的状态 不显示就continue
if(child.getVisibility()==View.GONE)
{
continue;
}
MarginLayoutParams lp=(MarginLayoutParams)child.getLayoutParams();
//获取子view的left top right bottom
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);
//一行内只改变自view的离左边距的位置
left+=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
}
//换行的时候left需要重置 top需要叠加
left=getPaddingLeft();//考虑flowlayout的padding
top+=lineHeight;
}
}
/*
* 与当前ViewGroup对应的LayoutParams
* */
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
}