前言:
RecyclerView可以使用GridLayoutManager实现跨行,但是不能跨列;瀑布流布局可以跨列但是又不能跨行。原生自带的各个LayoutManager中并没有可以又跨行又能跨列的。网上搜寻了一番,找到了一个亲测可行好用的三方库:spannedgridlayoutmanager。
实现效果预览:
依赖库的地址:
使用:
1、添加依赖:
dependencies {
implementation 'com.arasthel:spannedgridlayoutmanager:3.0.2'
}
如果依赖不成功或者想要自定义spannedgridlayoutmanager里面的代码,使用Module的方式来导入该项目。这边提供资源地址:spannedgridlayoutmanager-3.0.2资源-CSDN文库
2、代码中使用:
java
recyclerView.setAdapter(adapter);
//参数Orientation.VERTICAL表示列表竖向;4表示4列
SpannedGridLayoutManager gridLayoutManager = new SpannedGridLayoutManager(
SpannedGridLayoutManager.Orientation.VERTICAL, 4);
gridLayoutManager.setSpanSizeLookup(new SpannedGridLayoutManager.SpanSizeLookup(position -> {
int col = 1;
int row = 1;
switch (adapter.getItemViewType(position)) {
case ITEM_TYPE_1x2:
col = 2;
break;
case ITEM_TYPE_1x4:
col = 4;
break;
case ITEM_TYPE_2x1:
row = 2;
break;
case ITEM_TYPE_2x2:
col = 2;
row = 2;
break;
case ITEM_TYPE_1x1:
default:
break;
}
return new SpanSize(col, row);
}));
recyclerView.setLayoutManager(gridLayoutManager);
根据你每一项item所需要占的格子数大小设置所跨宽和列的单元格个数。
就可以啦。
完整代码:
这边代码包含了item拖动功能,详细解释和实现方式可以参考我另一篇博客:Android:RecyclerView自由拖动itemhttp://t.csdnimg.cn/bPdbl不需要拖拽功能的忽略即可。
适配器:
java
public class AppsCardAdapter extends RecyclerView.Adapter<AppsCardAdapter.MyHolder> {
private final List<Integer> mList;
private final Context mContext;
private final int ITEM_TYPE_1x1 = 0;
private final int ITEM_TYPE_1x2 = 1;
private final int ITEM_TYPE_1x4 = 2;
private final int ITEM_TYPE_2x2 = 3;
private final int ITEM_TYPE_2x1 = 4;
AppsCardAdapter(Context context) {
this.mContext = context;
mList = new ArrayList<>();
}
@NonNull
@Override
public MyHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int itemType) {
View rootView = LayoutInflater.from(mContext).inflate(
R.layout.item_apps_card, viewGroup, false);
return new MyHolder(rootView);
}
@SuppressLint("SetTextI18n")
@Override
public void onBindViewHolder(@NonNull MyHolder holder, int position) {
int item = mList.get(position);
holder.name.setText(item + "");
holder.itemView.setOnClickListener(view -> {
Toast.makeText(mContext, "item = "+item, Toast.LENGTH_SHORT).show();
});
}
@Override
public int getItemCount() {
return mList.size();
}
@Override
public int getItemViewType(int position) {
TODO: 根据实际项目item的类型来,这边为了演示直接定死位置的类型了
switch (mList.get(position)){
case 0:
return ITEM_TYPE_1x4;
case 1:
case 4:
case 6:
return ITEM_TYPE_1x2;
case 2:
case 3:
return ITEM_TYPE_2x1;
case 5:
return ITEM_TYPE_2x2;
default:
return ITEM_TYPE_1x1;
}
}
static class MyHolder extends RecyclerView.ViewHolder {
TextView name;
public MyHolder(@NonNull View itemView) {
super(itemView);
name = itemView.findViewById(R.id.name);
}
}
//拖动功能的回调类
private static class MyItemTouchHelperCallback extends ItemTouchHelper.Callback{
private final AppsCardAdapter appsCardAdapter;
public MyItemTouchHelperCallback(AppsCardAdapter appsCardAdapter) {
this.appsCardAdapter = appsCardAdapter;
}
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolder) {
if (viewHolder.getItemViewType() == appsCardAdapter.ITEM_TYPE_1x4) {
//不可拖动
return makeMovementFlags(0, 0);
}
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN
| ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
return makeFlag(ItemTouchHelper.ACTION_STATE_DRAG, dragFlags);
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolderSource,
@NonNull RecyclerView.ViewHolder viewHolderTarget) {
if (viewHolderTarget.getItemViewType() == appsCardAdapter.ITEM_TYPE_1x4) {
//不可拖动到这里
return false;
}
appsCardAdapter.onMove(viewHolderSource.getAdapterPosition(),
viewHolderTarget.getAdapterPosition());
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
}
}
private void onMove(int sourcePosition, int targetPosition) {
int item = mList.get(sourcePosition);
mList.remove(sourcePosition);
mList.add(targetPosition, item);
notifyItemMoved(sourcePosition, targetPosition);
}
public void setRecyclerView(RecyclerView recyclerView) {
recyclerView.setAdapter(this);
SpannedGridLayoutManager gridLayoutManager = new SpannedGridLayoutManager(
SpannedGridLayoutManager.Orientation.VERTICAL, 4);
gridLayoutManager.setSpanSizeLookup(new SpannedGridLayoutManager.SpanSizeLookup(position -> {
int col = 1;
int row = 1;
switch (getItemViewType(position)) {
case ITEM_TYPE_1x2:
col = 2;
break;
case ITEM_TYPE_1x4:
col = 4;
break;
case ITEM_TYPE_2x1:
row = 2;
break;
case ITEM_TYPE_2x2:
col = 2;
row = 2;
break;
case ITEM_TYPE_1x1:
default:
break;
}
return new SpanSize(col, row);
}));
recyclerView.setLayoutManager(gridLayoutManager);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(
new MyItemTouchHelperCallback(this));
itemTouchHelper.attachToRecyclerView(recyclerView);
}
public void setNewData(List<Integer> list) {
this.mList.clear();
this.mList.addAll(list);
notifyDataSetChanged();
}
}
Activity中使用:
java
AppsCardAdapter adapter = new AppsCardAdapter(getContext());
adapter.setRecyclerView(recyclerView);
//测试数据
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 13; i++) {
list.add(i);
}
adapter.setNewData(list);