RecycleView功能比较强大,自由度比较高,能实现各种各样的布局。对于像多列布局,或者增加header/footer这种情况,也是比较方便能够实现。下面一步一步来实现带有section的多列列表。
首先实现多列列表,这个就很容易直接布局样式改为GridLayoutManager,然后设置spanCount即可。如果某一列的item数目是不固定的,那么需要通过设置SpanSizeLookup来实现:
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
// 这里的position就是item所在的position
if (position == 0) {
// 例如第一行一列
return 1;
} else {
// 其他行展示两列
return 2;
}
}
});
接下来加入section header和footer,这里一般如果简单一点的布局直接在第一行加入header和最后一行加入footer,这里可以用itemViewType来实现不同的section,代码如下:
public class MainActivity extends AppCompatActivity {
private RecyclerView rvTest;
private MyAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvTest = findViewById(R.id.rv_test);
mAdapter = new MyAdapter();
final GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
rvTest.setLayoutManager(gridLayoutManager);
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
// 表示一个item占用几份
if (position == 0 || position == mAdapter.getItemCount()-1) {
// 由于GridLayoutManager设置的每行2份, header和footer要独占一行, 所以设置为2份, 也即spanCount
return gridLayoutManager.getSpanCount();
} else {
// 其他item占一半,也即是1份
return 1;
}
}
});
rvTest.setAdapter(mAdapter);
}
class MyAdapter extends RecyclerView.Adapter {
public static final int TYPE_HEADER = 0;
public static final int TYPE_FOOTER = 1;
public static final int TYPE_ITEM = 2;
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER) {
View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.header_layout, parent, false);
return new HeaderViewHolder(itemView);
} else if (viewType == TYPE_FOOTER){
View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.footer_layout, parent, false);
return new FooterViewHolder(itemView);
} else {
View itemView = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_layout, parent, false);
return new ItemViewHolder(itemView);
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
if (viewType == TYPE_HEADER) {
((HeaderViewHolder) holder).tvHeader.setText("我是header");
} else if (viewType == TYPE_FOOTER) {
((FooterViewHolder) holder).tvFooter.setText("我是footer");
} else {
((ItemViewHolder) holder).tvTest.setText("我是item");
}
}
@Override
public int getItemCount() {
return 10;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return TYPE_HEADER;
} else if (position == getItemCount()-1) {
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
class HeaderViewHolder extends RecyclerView.ViewHolder {
TextView tvHeader;
public HeaderViewHolder(@NonNull View itemView) {
super(itemView);
tvHeader = itemView.findViewById(R.id.tv_test);
}
}
class FooterViewHolder extends RecyclerView.ViewHolder {
TextView tvFooter;
public FooterViewHolder(@NonNull View itemView) {
super(itemView);
tvFooter = itemView.findViewById(R.id.tv_test);
}
}
class ItemViewHolder extends RecyclerView.ViewHolder {
TextView tvTest;
public ItemViewHolder(@NonNull View itemView) {
super(itemView);
tvTest = itemView.findViewById(R.id.tv_test);
}
}
}
}