package com.picovr.service.tobservice.view; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; public class FlowLayout extends ViewGroup { public FlowLayout(Context context, AttributeSet attrs) { super(context, attrs); } public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs); } public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { this(context, attrs, defStyleAttr); } @Override protected LayoutParams generateDefaultLayoutParams() { return new MarginLayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT); } @Override protected LayoutParams generateLayoutParams(LayoutParams p) { return new MarginLayoutParams(p); } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(),attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widhtmode = MeasureSpec.getMode(widthMeasureSpec); int heightmode = MeasureSpec.getMode(heightMeasureSpec); int measureWidth = MeasureSpec.getSize(widthMeasureSpec); int measureHeight = MeasureSpec.getSize(heightMeasureSpec); int lineWidht = 0; int lineHeight = 0; int widht = 0; int height = 0; int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { View childAt = getChildAt(i); measureChild(childAt,widthMeasureSpec,heightMeasureSpec); MarginLayoutParams lp = null; if (childAt.getLayoutParams() instanceof MarginLayoutParams){ lp = (MarginLayoutParams) childAt.getLayoutParams(); }else{ lp = new MarginLayoutParams(0,0); } int childwidht = childAt.getMeasuredWidth()+lp.leftMargin+lp.rightMargin; int childHeight = childAt.getMeasuredHeight()+lp.topMargin+lp.bottomMargin; if (lineWidht+childwidht >measureWidth){ widht = lineWidht; height+= lineHeight; lineHeight = childHeight; lineWidht = childwidht; }else{ lineHeight = Math.max(lineHeight, childHeight); lineWidht = childwidht; } if (i == childCount-1){ height += lineHeight; widht = Math.max(widht,lineWidht); } } setMeasuredDimension((widhtmode==MeasureSpec.EXACTLY)?measureWidth:widht,(heightmode==MeasureSpec.EXACTLY)?measureHeight:height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { //还是先获取所有的子view int count = getChildCount(); //定义列宽 int lineWidth = 0; //定义行高 int lineHeight = 0; //定义上、左边距 int top = 0,left=0; for (int i = 0; i < count; i++) { View childAt = getChildAt(i); MarginLayoutParams layoutParams = (MarginLayoutParams) childAt.getLayoutParams(); //因为onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法已经执行完,所有这里我们可以直接调用 //子view的宽+左右边距 int childWidth = childAt.getMeasuredWidth()+layoutParams.leftMargin+layoutParams.rightMargin; int childHeight = childAt.getMeasuredHeight()+layoutParams.topMargin+layoutParams.bottomMargin; //这里的if判断和onMeasure中是一样的逻辑,不再赘述 if(childWidth+lineWidth>getMeasuredWidth()){ //累加top top+=lineHeight; //因为换行了left置为0 left = 0; lineHeight = childHeight; lineWidth = childWidth; }else{ lineHeight = Math.max(lineHeight,childHeight); //行宽累加 lineWidth+=childWidth; } //计算子view的左、上、右、下的值 int lc = left+layoutParams.leftMargin; int tc = top+layoutParams.topMargin; //右边就等于自己的宽+左边的边距即lc int rc = lc+childAt.getMeasuredWidth(); //底部逻辑同上 int bc = tc+childAt.getMeasuredHeight(); //布局 childAt.layout(lc,tc,rc,bc); //这一句很重要,因为一行中有多个view,所有left是累加的关系。 left+=childWidth; } } }
Android流式布局
最新推荐文章于 2024-05-02 20:40:27 发布