项目需要实现一个柜格列表,主柜会应为硬件型号不同,某个item会有夸行效果.这边记录下.
实现效果
1. 自定义GridLayoutManager
GridLayoutManager网格布局可以设置item的spanSize,从而实现跨行或者跨列.
/**
* recycleView
* 1.方向为HORIZONTAL实现跨行, addItemDecoration()实现水平方向间隔,垂直方向间隔要单独处理.
* 2.方向为VERTICAL 实现跨列 ,addItemDecoration()实现垂直方向间隔,水平方向间隔要单独处理.
*/
public class CustomGridLayoutManager extends GridLayoutManager {
// 间隔 单方向
private final int spacing;
private static final String TAG = "SpanGridLayoutManager";
// 计算的列数
private int cachedColumnCount = -1;
// 计算的行数
private int cachedRowCount = -1;
/**
* @param context .
* @param spanCount HORIZONTAL:显示几行 VERTICAL:显示几列
* @param orientation .方向
* @param spacing .
* @param data map 跨行/跨列 key=position value=spanSize.
*/
public CustomGridLayoutManager(Context context, int spanCount, int orientation, int spacing, Map<Integer, Integer> data) {
super(context, spanCount, orientation, false);
this.spacing = spacing;
if (data != null && !data.isEmpty()) {
Set<Integer> keys = data.keySet();
setSpanSizeLookup(new SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
int spanSize = 1;
for (Integer key : keys) {
if (position == key)
spanSize = data.getOrDefault(key, 1);
}
return spanSize;
}
});
}
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
int spanCount = getSpanCount();
int totalSpacing = spanCount * spacing;
int itemCount = state.getItemCount();
if (getOrientation() == RecyclerView.HORIZONTAL) {
// RecyclerView.HORIZONTAL 纵向跨行
int cellHeight = (getHeight() - totalSpacing) / spanCount;
if (cachedColumnCount == -1) {
cachedColumnCount = calculateRowOrColumnCount(itemCount, spanCount);
}
// int columnCount = cachedColumnCount;
// if (columnCount <= 0) return;
if (cachedColumnCount <= 0) return;
int totalWidthSpacing = cachedColumnCount * spacing;
int cellWidth = (getWidth() - totalWidthSpacing) / cachedColumnCount;
Log.i(TAG, "onLayoutChildren: w= " + getWidth() + "-----h = " + getHeight() + "=== spanCount = " + spanCount);
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
if (view != null) {
int position = getPosition(view);
int spanSize = getSpanSizeLookup().getSpanSize(position);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
int newHeight;
if (spanSize > 1) {
newHeight = cellHeight * spanSize + (spanSize - 1) * spacing;
} else {
newHeight = cellHeight;
}
if (params.height != newHeight || params.width != cellWidth) {
params.height = newHeight;
params.width = cellWidth;
view.setLayoutParams(params);
}
}
}
} else {
// RecyclerView.VERTICAL 横向跨列
int cellWidth = (getWidth() - totalSpacing) / spanCount;
if (cachedRowCount == -1) {
cachedRowCount = calculateRowOrColumnCount(itemCount, spanCount);
}
// int rowCount = cachedRowCount;
//if (rowCount <= 0) return;
if (cachedRowCount <= 0) return;
int totalHeightSpacing = cachedRowCount * spacing;
int cellHeight = (getHeight() - totalHeightSpacing) / cachedRowCount;
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
if (view != null) {
int position = getPosition(view);
int spanSize = getSpanSizeLookup().getSpanSize(position);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams();
int newWidth;
if (spanSize > 1) {
newWidth = cellWidth * spanSize + (spanSize - 1) * spacing;
} else {
newWidth = cellWidth;
}
if (params.height != cellHeight || params.width != newWidth) {
params.height = cellHeight;
params.width = newWidth;
view.setLayoutParams(params);
}
}
}
}
}
/**
* 计算行数或列数
*
* @param itemCount recycleView item总数量
* @param spanCount = 5 ,HORIZONTAL:代表5行 VERTICAL:代表5列
* @return 行数或列数
*/
private int calculateRowOrColumnCount(int itemCount, int spanCount) {
int count = 0;
for (int i = 0; i < itemCount; i++) {
int spanSize = getSpanSizeLookup().getSpanSize(i);
if (spanSize > 1) {
count += spanSize - 1;
}
}
return (int) Math.ceil((double) (itemCount + count) / spanCount);
}
}
2. 使用
CustomGridLayoutManager 构造的data集合可以添加多个item的position,并设置对应的spanSize
- 设置LinearLayoutManager.VERTICAL item跨列
- 设置LinearLayoutManager.HORIZONTALitem跨行
List<String> list = new ArrayList<>();
for (int i = 0; i < 18; i++) {
list.add((i + 1) + "");
}
MyAdapter myAdapter = new MyAdapter(list);
viewBinging.recycleview.setAdapter(myAdapter);
Map<Integer, Integer> data = new HashMap<>();
data.put(0, 2);
data.put(7, 2);
CustomGridLayoutManager layoutManager = new CustomGridLayoutManager(mContext, 4,
LinearLayoutManager.VERTICAL, 10, data);
viewBinging.recycleview.setLayoutManager(layoutManager);
viewBinging.recycleview.addItemDecoration(new SpacingItemDecoration(10));
//viewBinging.recycleview.setOverScrollMode(View.OVER_SCROLL_NEVER);
end.