最近在开发过程中,遇到这样一个需求,就是对数组分组显示,在网上找了很多方案,但都讲得不全面,在此记录一下自己实践成功的方案。如下图:
具体步骤
第一步、使用RecycleView实现,并设置layoutManager为GridLayoutManager。
int column = Utils.calculateCashBackStoreSpanCount(getContext());
GridLayoutManager layoutManager = new GridLayoutManager(getContext(), column);
recycleView.setLayoutManager(layoutManager);
第二步、使adapter支持多类型,例如:
需要加入开源库
versions.base_adapter = "3.0.3"
compile "com.zhy:base-rvadapter:$versions.base_adapter"
public class StoreGridAdapter extends MultiItemTypeAdapter
第三步、计算间距。大概说一下算法:首先识别item是否是label,然后设置label间距;其次计算item所在位置是不是新行开始。代码如下:
class MyItemDecoration extends RecyclerView.ItemDecoration {
private int space;
private int spanCount;
MyItemDecoration (int cols, int space){
this.spanCount = cols;
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
int position = parent.getChildAdapterPosition(view); // item position
spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
if(position == 0) {
outRect.top = space;
}
if(isAds(parent, position)) {
outRect.top = 0;
outRect.left = 0;
outRect.right = 0;
}else if(isLabel(parent, position)) {
//label
outRect.left = space*2;
outRect.right = space;
}else{
if(isNewLine(parent, position)) {
outRect.left = space;
outRect.right = space;
}else{
outRect.right = space;
}
}
outRect.bottom = space;
}
private boolean isLabel(RecyclerView parent, int position){
int viewType = parent.getAdapter().getItemViewType(position);
return (viewType == AllStoreGridAdapter.ITEM_TYPE_LABEL);
}
private boolean isNewLine(RecyclerView parent, int position){
boolean newLine = false;
if(isLabel(parent, position-1)){
return true;
}
int startIndex = findAreaStartIndex(parent, position);
if(startIndex > -1) {
return ((position-1 - startIndex) % spanCount == 0);
}
return newLine;
}
private int findAreaStartIndex(RecyclerView parent, int position){
for(int i=position; i<= position; i--){
if(isLabel(parent, i)){
return i;
}
}
return -1;
}
private boolean isAds(RecyclerView parent, int position){
int viewType = parent.getAdapter().getItemViewType(position);
return (viewType == AllStoreGridAdapter.ITEM_TYPE_ADS);
}
}
总结
RecycleView控件可以绘制出各种各样的布局效果,秘诀就是合理使用layoutManager,动态item的带下和间距。