import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; /** * 流式布局 * * 用法 * 1、可以直接当做一个父布局使用 类似LinearLayout在布局中给其添加布局 * 2、如果在代码中添加布局 需要给需要添加的child设置MarginLayoutParams 例如下面是添加一个TextView的例子 * 需要在代码中设置TextView的宽高 和margin值 * * 例子: * TextView textView = new TextView(this); * ViewGroup.MarginLayoutParams marginLayoutParams * = new ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, * ViewGroup.LayoutParams.WRAP_CONTENT); * textView.setLayoutParams(marginLayoutParams); * flowLayout.addView(textView); * * Created by linyaokui on 2017/11/6. */ public class FlowLayout extends ViewGroup { /** * 用来保存每行views的列表 */ private List<List<View>> mViewLinesList; /** * 用来保存行高的列表 */ private List<Integer> mLineHeights; 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); } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(),attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mViewLinesList = new ArrayList<>(); mLineHeights = new ArrayList<>(); // 获取父容器为FlowLayout设置的测量模式和大小 int iWidthMode = MeasureSpec.getMode(widthMeasureSpec); int iHeightMode = MeasureSpec.getMode(heightMeasureSpec); int iWidthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int iHeightSpecSize = MeasureSpec.getSize(heightMeasureSpec); int measuredWith = 0; int measuredHeight = 0; int iCurLineW = 0; //当前行的宽度 int iCurLineH = 0; //当前行的高度 int iChildWidth; int iChildHeight; int childCount = getChildCount(); List<View> viewList = new ArrayList<>(); for(int i = 0 ; i < childCount ; i++){ View childView = getChildAt(i); measureChild(childView, widthMeasureSpec,heightMeasureSpec); MarginLayoutParams layoutParams = (MarginLayoutParams) childView.getLayoutParams(); iChildWidth = childView.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin; iChildHeight = childView.getMeasuredHeight() + layoutParams.topMargin + layoutParams.bottomMargin; if(iCurLineW + iChildWidth > iWidthSpecSize){ /**1、记录当前行的信息***/ //1、记录当前行的最大宽度,高度累加 measuredWith = Math.max(measuredWith,iCurLineW); measuredHeight += iCurLineH; //2、将当前行的viewList添加至总的mViewsList,将行高添加至总的行高List mViewLinesList.add(viewList); mLineHeights.add(iCurLineH); /**2、记录新一行的信息***/ //1、重新赋值新一行的宽、高 iCurLineW = iChildWidth; iCurLineH = iChildHeight; // 2、新建一行的viewlist,添加新一行的view viewList = new ArrayList<>(); viewList.add(childView); }else{ // 记录某行内的消息 //1、行内宽度的叠加、高度比较 iCurLineW += iChildWidth; iCurLineH = Math.max(iCurLineH, iChildHeight); // 2、添加至当前行的viewList中 viewList.add(childView); } /*****3、前面没有记录最后一行的信息 在这里记录**********/ if(i == childCount - 1){ //1、记录当前行的最大宽度,高度累加 measuredWith = Math.max(measuredWith,iCurLineW); measuredHeight += iCurLineH; //2、将当前行的viewList添加至总的mViewsList,将行高添加至总的行高List mViewLinesList.add(viewList); mLineHeights.add(iCurLineH); } } if(iWidthMode == MeasureSpec.EXACTLY ){ measuredWith = iWidthSpecSize; } if(iHeightMode == MeasureSpec.EXACTLY){ measuredHeight = iHeightSpecSize;} setMeasuredDimension(measuredWith,measuredHeight); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int left,top,right,bottom; int curTop = 0; int curLeft = 0; int lineCount = mViewLinesList.size(); for(int i = 0 ; i < lineCount ; i++) { List<View> viewList = mViewLinesList.get(i); int lineViewSize = viewList.size(); for(int j = 0; j < lineViewSize; j++){ View childView = viewList.get(j); MarginLayoutParams layoutParams = (MarginLayoutParams) childView.getLayoutParams(); left = curLeft + layoutParams.leftMargin; top = curTop + layoutParams.topMargin; right = left + childView.getMeasuredWidth(); bottom = top + childView.getMeasuredHeight(); childView.layout(left,top,right,bottom); curLeft += childView.getMeasuredWidth() + layoutParams.leftMargin + layoutParams.rightMargin; } curLeft = 0; curTop += mLineHeights.get(i); } mViewLinesList.clear(); mLineHeights.clear(); } public interface OnItemClickListener{ void onItemClick (View v, int index); } public void setOnItemClickListener(final OnItemClickListener listener){ int childCount = getChildCount(); for(int i = 0 ; i < childCount ; i++){ View childView = getChildAt(i); final int finalI = i; childView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { listener.onItemClick(v, finalI); } }); } } }
Android流式布局
最新推荐文章于 2024-06-19 00:17:52 发布