本文为菜鸟窝作者蒋志碧的连载。“从 0 开始开发一款直播 APP ”系列来聊聊时下最火的直播 APP,如何完整的实现一个类"腾讯直播"的商业化项目
视频地址:http://www.cniao5.com/course/10121
【从 0 开始开发一款直播 APP】3.1 高层封装之 Adapter — ListView & GridView
【从 0 开始开发一款直播 APP】3.2 高层封装之 Adapter — RecyclerView 实现单布局展示
【从 0 开始开发一款直播 APP】3.3 高层封装之 Adapter -- RecyclerView 实现多条目展示
【从 0 开始开发一款直播 APP】3.4 高层封装之 Adapter -- RecyclerView 优雅的添加 Header、Footer
一、多条目 Adapter 封装实现聊天界面
上章已经讲解了 RecyclerView 的基本封装,这次对于多条目展示进行讲解,效果如下:
RecyclerView.Adapter 的 getItemViewType(int position) 这个方法,可以根据当前位置获取一个 viewType 最终会传到 onCreateViewHolder() 这个方法中, 通过一个标识来判断条目的布局。
1.1、定义一个接口,用来获取布局
public interface MutipleTypeSupport {
//根据当前条目获取布局
int getLayoutId(T t);
}
1.2、在原来的Adapter基础上做修改,将MutipleTypeSupport接口传入,让用户传递布局类型
private MutipleTypeSupport mMutipleTypeSupport;
public RecyclerViewAdapter(Context context,List datas,MutipleTypeSupport typeSupport){
this(context,-1,datas);
this.mMutipleTypeSupport = typeSupport;
}
1.3、根据 getItemViewType 获取当前位置的 item 类型, position 就是当前 item 的值
//调用 onCreateViewHolder() 方法之前调用 getItemViewType()
@Override
public int getItemViewType(int position) {
if (mMutipleTypeSupport != null){
return mMutipleTypeSupport.getLayoutId(mDatas.get(position));
}
return super.getItemViewType(position);
}
@Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//判断是否需要多布局
if (mMutipleTypeSupport != null){
mLayoutId = viewType;
}
View itemView = mInflater.inflate(mLayoutId,parent,false);
return new RecyclerViewHolder(itemView);
}
1.4、其它方法不变,所有代码
public abstract class RecyclerViewAdapter extends RecyclerView.Adapter {
protected int mLayoutId;
protected List mDatas;
protected Context mContext;
private LayoutInflater mInflater;
private MutipleTypeSupport mMutipleTypeSupport;
public RecyclerViewAdapter(Context context,List datas,MutipleTypeSupport typeSupport){
this(context,-1,datas);
this.mMutipleTypeSupport = typeSupport;
}
public RecyclerViewAdapter(Context context, int layoutId, List datas) {
this.mContext = context;
this.mLayoutId = layoutId;
this.mDatas = datas;
this.mInflater = LayoutInflater.from(mContext);
}
//调用onCreateViewHolder方法之前调用getItemViewType
@Override
public int getItemViewType(int position) {
//如果支持多布局,返回所有布局
if (mMutipleTypeSupport != null){
return mMutipleTypeSupport.getLayoutId(mDatas.get(position));
}
return super.getItemViewType(position);
}
@Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//多布局支持
if (mMutipleTypeSupport != null){
mLayoutId = viewType;
}
View itemView = mInflater.inflate(mLayoutId,parent,false);
return new RecyclerViewHolder(itemView);
}
@Override
public void onBindViewHolder(RecyclerViewHolder holder, final int position) {
//ViewHolder优化
bindData(holder,mDatas.get(position),position);
}
/**
* 把必要参数传进去
* @param holder RecyclerViewHolder
* @param t 数据
* @param position 当前位置
*/
protected abstract void bindData(RecyclerViewHolder holder, T t,int position);
@Override
public int getItemCount() {
return mDatas.size();
}
}
封装完就写的 Demo 看看效果吧。
二、多布局 Demo 实现
2.1、 MutipleAdapter 继承 RecyclerViewAdapter ,通过 getLayoutId() 传递布局
public class MutipleAdaper extends RecyclerViewAdapter- {
public MutipleAdaper(Context context, List
- datas) {
super(context, datas, new MutipleTypeSupport
- () {
@Override
public int getLayoutId(Item item) {
if (item.getType() == 1){//该处1是通过 item 传过来的
return R.layout.list_item;
}else {
return R.layout.list_item1;
}
}
});
}
@Override
protected void bindData(RecyclerViewHolder holder, final Item item, int position) {
holder.setText(R.id.tv1,item.getTv1())
.setImageResource(R.id.img,item.getRes())
.setOnClickListener(R.id.tv1, new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext,item.getTv1(),Toast.LENGTH_SHORT).show();
}
});
}
}
**2.2、 AdapterActivity **
public class AdapterActivity extends BaseActivity {
private MutipleAdaper mMutipleAdaper;
private RecyclerView mRecyclerView;
@Override
protected void setToolbar() {
}
@Override
protected void setListener() {
}
//填充数据
@Override
protected void initData() {
Datas = new ArrayList<>();
for (int i = 1; i <= 30; i++) {
if (i % 2 == 0) {
Datas.add(new Item(R.drawable.tab_publish_normal,"我 get 新技能 " + i,0));//根据 Item 类 最后一个参数确定填充数据的不同
}else {
Datas.add(new Item(R.drawable.tab_publish_normal,"你 get 新技能 " + i,1));
}
}
mMutipleAdaper = new MutipleAdaper(this,Datas);
mRecyclerView.setAdapter(mMutipleAdaper);
}
@Override
protected void initView() {
mRecyclerView = obtainView(R.id.recyclerView);
mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
}
@Override
protected int getLayoutId() {
return R.layout.activity_adapter;
}
}
2.3、 Item 类
public class Item {
private int res;//图片
private String tv1;//文字
private int type;//类型
public Item(int res, String tv1,int type) {
this.res = res;
this.tv1 = tv1;
this.type = type;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getRes() {
return res;
}
public void setRes(int res) {
this.res = res;
}
public String getTv1() {
return tv1;
}
public void setTv1(String tv1) {
this.tv1 = tv1;
}
}
对于RecyclerView 实现多布局讲解完毕,下一章继续为大家讲解 RecyclerView 封装之优雅添加 Header、Footer。
总结
多条目的封装
1、在单条目基础上通过构造函数传递一个提供布局的接口,通过 ViewType 类型判断到底使用什么布局。
2、在 getItemViewType() 方法中判断布局类型,在 onCreateViewHolder() 方法中判断是否需要多布局,根据用户需要实现不同的构造函数