public class MyFlowView extends ViewGroup {
public MyFlowView(Context context) {
this(context,null);
}
public MyFlowView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyFlowView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//测量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//总的宽度和高度
int width=0;
int height=0;
//记录每一行的宽度和高度
int lineWidth=0;
int lineHeight=0;
//宽度相关
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
//高度相关
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
for (int i=0;i<getChildCount();i++){
View childAt = getChildAt(i);
//测量子view的宽和高
measureChild(childAt,widthMeasureSpec,heightMeasureSpec);
//得到LayoutParms
MarginLayoutParams lp= (MarginLayoutParams) childAt.getLayoutParams();
//得到子view的宽度和高度
int childWidth = childAt.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
int childHeight = childAt.getMeasuredHeight()+lp.topMargin+lp.bottomMargin;
//换行
if(lineWidth+childWidth>sizeWidth-getPaddingLeft()-getPaddingRight()){
//对比得到最大宽度
width=Math.max(width,lineWidth);
//重置行宽
lineWidth=childWidth;
//累加高度
height+=lineHeight;
//重置行高
lineHeight=childHeight;
}else{
//叠加行宽
lineWidth+=childWidth;
//得到最大行高
lineHeight=Math.max(lineHeight,childHeight);
}
if(i==getChildCount()-1){
width=Math.max(width,lineWidth);
height+=lineHeight;
}
}
switch (modeWidth){
case MeasureSpec.EXACTLY:
width=sizeWidth;
break;
case MeasureSpec.AT_MOST:
width+=getPaddingLeft()+getPaddingRight();
break;
case MeasureSpec.UNSPECIFIED:
break;
}
switch (modeHeight){
case MeasureSpec.EXACTLY:
height=sizeHeight;
break;
case MeasureSpec.AT_MOST:
height+=getPaddingTop()+getPaddingBottom();
break;
case MeasureSpec.UNSPECIFIED:
break;
}
setMeasuredDimension(width,height);
}
//存放所有的view 是按照每一行的view来存储
private List<List<View>> mAllViews=new ArrayList();
//存储每一行的高度
private List<Integer> mLineHeight=new ArrayList<Integer>();
//布局
@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<>();
for (int i=0;i<getChildCount();i++){
View child = getChildAt(i);
MarginLayoutParams lp= (MarginLayoutParams) child.getLayoutParams();
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
if(childWidth+lineWidth+lp.leftMargin+lp.rightMargin>width-getPaddingLeft()-getPaddingRight()){
mLineHeight.add(lineHeight);
mAllViews.add(lineViews);
//重置行宽
lineWidth=0;
lineHeight=childHeight+lp.topMargin+lp.bottomMargin;
lineViews=new ArrayList<>();
}
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();
for (int i=0;i<mAllViews.size();i++){
//得到当前行的高和视图
lineViews = mAllViews.get(i);
lineHeight=mLineHeight.get(i);
for (int j=0;j<lineViews.size();j++){
View child = lineViews.get(j);
//判断可见性
if(child.getVisibility()==View.GONE){
continue;
}
MarginLayoutParams lp= (MarginLayoutParams) child.getLayoutParams();
int lc=left+lp.leftMargin;
int tc=top+lp.topMargin;
int rc=lc+child.getMeasuredWidth();
int bc=tc+child.getMeasuredHeight();
child.layout(lc,tc,rc,bc);
left+=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
}
left=getPaddingLeft();
top+=lineHeight;
}
}
/**
* 这个方法主要是用于父容器添加子View时调用,
用于生成和此容器类型相匹配的布局参数类。
* @param attrs
* @return
*/
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(),attrs);
}
}
public MyFlowView(Context context) {
this(context,null);
}
public MyFlowView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyFlowView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//测量
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//总的宽度和高度
int width=0;
int height=0;
//记录每一行的宽度和高度
int lineWidth=0;
int lineHeight=0;
//宽度相关
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
//高度相关
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
for (int i=0;i<getChildCount();i++){
View childAt = getChildAt(i);
//测量子view的宽和高
measureChild(childAt,widthMeasureSpec,heightMeasureSpec);
//得到LayoutParms
MarginLayoutParams lp= (MarginLayoutParams) childAt.getLayoutParams();
//得到子view的宽度和高度
int childWidth = childAt.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
int childHeight = childAt.getMeasuredHeight()+lp.topMargin+lp.bottomMargin;
//换行
if(lineWidth+childWidth>sizeWidth-getPaddingLeft()-getPaddingRight()){
//对比得到最大宽度
width=Math.max(width,lineWidth);
//重置行宽
lineWidth=childWidth;
//累加高度
height+=lineHeight;
//重置行高
lineHeight=childHeight;
}else{
//叠加行宽
lineWidth+=childWidth;
//得到最大行高
lineHeight=Math.max(lineHeight,childHeight);
}
if(i==getChildCount()-1){
width=Math.max(width,lineWidth);
height+=lineHeight;
}
}
switch (modeWidth){
case MeasureSpec.EXACTLY:
width=sizeWidth;
break;
case MeasureSpec.AT_MOST:
width+=getPaddingLeft()+getPaddingRight();
break;
case MeasureSpec.UNSPECIFIED:
break;
}
switch (modeHeight){
case MeasureSpec.EXACTLY:
height=sizeHeight;
break;
case MeasureSpec.AT_MOST:
height+=getPaddingTop()+getPaddingBottom();
break;
case MeasureSpec.UNSPECIFIED:
break;
}
setMeasuredDimension(width,height);
}
//存放所有的view 是按照每一行的view来存储
private List<List<View>> mAllViews=new ArrayList();
//存储每一行的高度
private List<Integer> mLineHeight=new ArrayList<Integer>();
//布局
@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<>();
for (int i=0;i<getChildCount();i++){
View child = getChildAt(i);
MarginLayoutParams lp= (MarginLayoutParams) child.getLayoutParams();
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
if(childWidth+lineWidth+lp.leftMargin+lp.rightMargin>width-getPaddingLeft()-getPaddingRight()){
mLineHeight.add(lineHeight);
mAllViews.add(lineViews);
//重置行宽
lineWidth=0;
lineHeight=childHeight+lp.topMargin+lp.bottomMargin;
lineViews=new ArrayList<>();
}
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();
for (int i=0;i<mAllViews.size();i++){
//得到当前行的高和视图
lineViews = mAllViews.get(i);
lineHeight=mLineHeight.get(i);
for (int j=0;j<lineViews.size();j++){
View child = lineViews.get(j);
//判断可见性
if(child.getVisibility()==View.GONE){
continue;
}
MarginLayoutParams lp= (MarginLayoutParams) child.getLayoutParams();
int lc=left+lp.leftMargin;
int tc=top+lp.topMargin;
int rc=lc+child.getMeasuredWidth();
int bc=tc+child.getMeasuredHeight();
child.layout(lc,tc,rc,bc);
left+=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;
}
left=getPaddingLeft();
top+=lineHeight;
}
}
/**
* 这个方法主要是用于父容器添加子View时调用,
用于生成和此容器类型相匹配的布局参数类。
* @param attrs
* @return
*/
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(),attrs);
}
}