Android流式布局

来源:互联网 发布:网络销售自我评价 编辑:程序博客网 时间:2024/06/07 21:54
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);                }            });        }    }}