自定义view实现流式布局

来源:互联网 发布:淘宝直通车的作用 编辑:程序博客网 时间:2024/05/20 10:12

显示效果如下,自定义view,重写onMeasure方法,测量wrap_content模式下控件的宽高,重写onLayout的方法,布局里面的子view,支持paddign属性.其实整个逻辑并不复杂,各位猿友可别复制粘贴啊!

这里写图片描述

/** * Created by Administrator on 2017/7/24. */public class MyFlowLayout extends ViewGroup{    //存储所有的view,行数就是该集合的元素个数    private List<List<View>> mAllViews=new ArrayList<>();    //记录每一行的行高,行数就是该集合的元素个数    private List<Integer> mLineHeight=new ArrayList<>();    public MyFlowLayout(Context context) {        this(context,null);    }    public MyFlowLayout(Context context, AttributeSet attrs) {        this(context, attrs,0);    }    public MyFlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        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;        //得到内部元素的个数        int cCount=getChildCount();        for (int i = 0; i < cCount; i++) {            View child = getChildAt(i);            //测量子view的宽和高            measureChild(child,widthMeasureSpec,heightMeasureSpec);            //得到layoutParams            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);                //重置lineWidth                lineWidth=childWidth;                //记录行高                height+=lineHeight;                lineHeight=childHeight;            }            else            {                //叠加行宽                lineWidth+=childWidth;                //得到当前行最大的高度                lineHeight=Math.max(lineHeight,childHeight);            }            //如果是最后一个控件            if (i==cCount-1)            {                width=Math.max(width,lineWidth);                height+=lineHeight;            }        }        setMeasuredDimension(modeWidth==MeasureSpec.EXACTLY?sizeWidth:width+getPaddingLeft()+getPaddingRight(),                                modeHeight==MeasureSpec.EXACTLY?sizeHeight:height+getPaddingBottom()+getPaddingTop());        //super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }    @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<>();        int cCount=getChildCount();        for (int i = 0; i < cCount; i++) {            View child = getChildAt(i);            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();            int childWidth=child.getMeasuredWidth();            int childHeight=child.getMeasuredHeight();            //如果需要换行            if (childWidth+lp.leftMargin+lp.rightMargin+lineWidth>width)            {                //记录lineHeight                mLineHeight.add(lineHeight);                //记录当期的views                mAllViews.add(lineViews);                //重置我们的行宽和行高                lineWidth=0;                lineHeight=childHeight+lp.topMargin+lp.bottomMargin;                //重置我们的view集合                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();        //行数        int lineNum=mAllViews.size();        for (int i = 0; i < lineNum; i++) {            lineViews=mAllViews.get(i);            lineHeight = mLineHeight.get(i);            for (int j = 0; j < lineViews.size(); j++) {                View child = lineViews.get(j);                //判断child的状态                if (child.getVisibility()==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();                //为子view进行布局                child.layout(lc,tc,rc,bc);                left+=child.getMeasuredWidth()+lp.leftMargin+lp.rightMargin;            }            left=getPaddingLeft();            top+=lineHeight;        }    }    //与当前viewgroup对应的layoutParams    @Override    public LayoutParams generateLayoutParams(AttributeSet attrs) {        return new MarginLayoutParams(getContext(),attrs);    }}
阅读全文
0 0
原创粉丝点击