在这里我们先看下效果图
这是用自定义的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