最近项目上需要实现一个搜索历史的一个布局,由于每次的搜索内容文本长度完全不同,因此布局的时候不可能采用Linear或Grid布局,需要自定义一种布局
RrecycleView的布局都是代理给RecyclerView.LayoutManager去处理的,因此自定义的布局管理器继承自此类,然后重写onLayoutChildren方法去计算布局,详细代码如下
package com.demo;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class AutoLineFeedLayoutManager extends RecyclerView.LayoutManager {
public AutoLineFeedLayoutManager() {
setAutoMeasureEnabled(true);//layoutmanager必须调用此方法设为true才能在onMesure时自动布局
}
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(
RecyclerView.LayoutParams.WRAP_CONTENT,
RecyclerView.LayoutParams.WRAP_CONTENT);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
detachAndScrapAttachedViews(recycler);
int curLineWidth = 0, curLineTop = 0;//curLineWidth 累加item布局时的x轴偏移curLineTop 累加item布局时的x轴偏移
int lastLineMaxHeight = 0;
for (int i = 0; i < getItemCount(); i++) {
View view = recycler.getViewForPosition(i);
//获取每个item的布局参数,计算每个item的占用位置时需要加上margin
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
addView(view);
measureChildWithMargins(view, 0, 0);
int width = getDecoratedMeasuredWidth(view) + params.leftMargin + params.rightMargin;
int height = getDecoratedMeasuredHeight(view) + params.topMargin + params.bottomMargin;
curLineWidth += width;//累加当前行已有item的宽度
if (curLineWidth <= getWidth()) {//如果累加的宽度小于等于RecyclerView的宽度,不需要换行
layoutDecorated(view, curLineWidth - width + params.leftMargin, curLineTop + params.topMargin, curLineWidth - params.rightMargin, curLineTop + height - params.bottomMargin);//布局item的真实位置
//比较当前行多有item的最大高度,用于换行后计算item在y轴上的偏移量
lastLineMaxHeight = Math.max(lastLineMaxHeight, height);
} else {//换行
curLineWidth = width;
if (lastLineMaxHeight == 0) {
lastLineMaxHeight = height;
}
//记录当前行top
curLineTop += lastLineMaxHeight;
layoutDecorated(view, params.leftMargin, curLineTop + params.topMargin, width - params.rightMargin, curLineTop + height - params.bottomMargin);
lastLineMaxHeight = height;
}
}
}
}
写好LayoutManager之后使用时只需要new一个此Manager然后设置给RecyclerView即可,如下
RecyclerView recycler = (RecyclerView)findViewById(R.id.recycler);
recycler.setLayoutManager(new AutoLineFeedLayoutManager());
如上代码设置后,item布局时会尽量布局在一行,当此行显示不下时自动换行,效果如下图