在這里我們先看下效果圖
image.png
這是用自定義的ViewGroup來(lái)實(shí)現(xiàn)的。
首先我們來(lái)分析要實(shí)現(xiàn)這個(gè)效果蟋定,我們要先拿到我們總共有多少個(gè)子View,然后我們?nèi)ケ闅v我們的子View草添,我們?nèi)缓笕y(cè)量我們的屏幕寬度驶兜,然后在確定我們一行顯示的view的寬度總和是不是大于我們屏幕的寬度,要是大于我們就得換行來(lái)顯示远寸,否則我們就在這一行顯示抄淑。當(dāng)換行的時(shí)候我們的高度肯定要去疊加,它的新的一行開始的寬度驰后,就是當(dāng)前這個(gè)view的寬度
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);
//自行這段話就會(huì)執(zhí)行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存放在一個(gè)List集合里面肆资,因?yàn)槲覀僶nMeasure之后我們還要去擺放子View的位置,調(diào)用onLayout方法灶芝。
然后我們?cè)跍y(cè)量的時(shí)候還要加它的Margin郑原,但是我們的的Viewgroup.LayoutParams,沒有獲取margin的方法,我們?nèi)タ碙inearLayout的LayoutParams的源碼夜涕,它去繼承了系統(tǒng)的MarginLayoutParams犯犁,那我們也就用它,就可以拿到我們的margin女器,我們代碼里面也這樣用酸役,不懂得同學(xué)可以去自己試下。
下面就是我們的onlayout的代碼驾胆,其實(shí)也和onMeasure的邏輯差不多涣澡,一行能夠顯示,就一行俏拱,不行就換行暑塑,疊加高度,重置left锅必。
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left, top = getPaddingTop(), right, bootom;
for (List<View> 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;
}
}
之后我們寫一個(gè)adapter然后給它設(shè)置進(jìn)去就行了事格,源碼在github上