自定义ViewGroup,实现流式布局

在这里我们先看下效果图


自定义ViewGroup,实现流式布局_第1张图片
image.png

这是用自定义的ViewGroup来实现的。
首先我们来分析要实现这个效果,我们要先拿到我们总共有多少个子View,然后我们去遍历我们的子View,我们然后去测量我们的屏幕宽度,然后在确定我们一行显示的view的宽度总和是不是大于我们屏幕的宽度,要是大于我们就得换行来显示,否则我们就在这一行显示。当换行的时候我们的高度肯定要去叠加,它的新的一行开始的宽度,就是当前这个view的宽度

    for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            //自行这段话就会执行child的onMeasure
            measureChild(childView, widthMeasureSpec, heightMeasureSpec);
            ViewGroup.MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams();
            if (lineWidth + (childView.getMeasuredWidth() + params.rightMargin + params.leftMargin) > width) {
                //换行累加高度
                height += childView.getMeasuredHeight() + params.topMargin + params.bottomMargin + childView.getPaddingTop() + childView.getPaddingBottom();
                lineWidth = childView.getMeasuredWidth() + params.rightMargin + params.leftMargin + childView.getPaddingRight() + childView.getPaddingLeft();
                childViews = new ArrayList<>();
                mChildViews.add(childViews);
            } else {
                lineWidth += childView.getMeasuredWidth() + params.rightMargin + params.leftMargin + childView.getPaddingRight() + childView.getPaddingLeft();
                maxHeight = Math.max(childView.getMeasuredHeight() + params.topMargin + params.bottomMargin + childView.getPaddingTop() + childView.getPaddingBottom(), maxHeight);
            }
            childViews.add(childView);
            height += maxHeight;
        }

在这里我们将我们的view存放在一个List集合里面,因为我们onMeasure之后我们还要去摆放子View的位置,调用onLayout方法。
然后我们在测量的时候还要加它的Margin,但是我们的的Viewgroup.LayoutParams,没有获取margin的方法,我们去看LinearLayout的LayoutParams的源码,它去继承了系统的MarginLayoutParams,那我们也就用它,就可以拿到我们的margin,我们代码里面也这样用,不懂得同学可以去自己试下。
下面就是我们的onlayout的代码,其实也和onMeasure的逻辑差不多,一行能够显示,就一行,不行就换行,叠加高度,重置left。

 @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left, top = getPaddingTop(), right, bootom;

        for (List childViews : mChildViews) {
            left = getPaddingLeft();
            for (View childView : childViews) {
                ViewGroup.MarginLayoutParams params = (MarginLayoutParams) childView.getLayoutParams();


                left += params.leftMargin + childView.getPaddingLeft();
                int childTop = top + params.topMargin + childView.getPaddingTop();
                right = childView.getMeasuredWidth() + left;
                bootom = childView.getMeasuredHeight() + childTop;

                childView.layout(left, childTop, right, bootom);
                Log.e(TAG, "onLayout:left " + left + "top" + top + "right" + right + "bootom" + bootom);
                //left叠加
                left += childView.getMeasuredWidth() + params.rightMargin + childView.getPaddingRight();
            }
            // 不断的叠加top值
            ViewGroup.MarginLayoutParams params = (MarginLayoutParams) childViews.get(0).getLayoutParams();
            top += childViews.get(0).getMeasuredHeight() + params.topMargin + params.bottomMargin;
        }
    }

之后我们写一个adapter然后给它设置进去就行了,源码在github上

https://github.com/chenzhikaizg/ViewGroupDemo

你可能感兴趣的:(自定义ViewGroup,实现流式布局)