RecyclerView多样式Item布局设计

说明
因为RecyclerView使用灵活方便导致开发中使用越来越频繁,特别是多样式的Item布局使用RecyclerView来显示比起以前使用ScrollView嵌套ListView,GridView要简单灵活多了。通过参考别人对RecyclerView多条目样式封装,也尝试着写了一个关于RecyclerView多样式的Item布局。
先看个效果图:
这里写图片描述
实现原理
实现原理跟ListView的多样式Item实现有点类似:
1. 通过getItemViewType(position)获取对应position上Model的类型,我们可以把Model抽取一个获取类型的接口;
2. 在onCreateViewHolder(ViewGroup parent, int viewType)中直接把Item的类型作为参数给出来了,我们就可以在这个方法通过viewType参数创建不同类型的RecyclerView.ViewHolder;
3. 然后在onBindViewHolder(BaseViewHolder holder, int position)方法中将数据Model和position绑定到不同的ViewHolder中;
4. 因为onBindViewHolder中把数据放到Model对应的ViewHolder里面去绑定,所以我在这里定义BaseViewHolder接口,绑定不同ViewHolder的数据;
5. 在2中创建不同的ViewHolder统一写在一个适配器中,代码逻辑会比较复杂,不便于扩展,所以我们可以通过类型工厂来产生不同的ViewHolder。
6. 因为不同类型的Item对应着不同布局文件,我们这里用资源文件ID作为类型,通过工厂获取不同Model的类型,不同类型工厂产生不同ViewHolder。
实现步骤
步骤1
抽象出Factory,Model,ViewHolder提供扩展。

  1. 创建工厂接口
    public interface TypeFactory {
    int type(Visitable visitable);
    BaseViewHolder createViewHolder(int type, View itemView);
    }
  2. 创建ViewHolder抽象类
    public abstract class BaseViewHolder extends RecyclerView.ViewHolder {
    public BaseViewHolder(View itemView) {
    super(itemView);
    }
    public abstract void bindData(T model, int position, MultiTypeAdapter adapter);
    }
  3. 创建Model接口
    public interface Visitable {
    int type(TypeFactory typeFactory);
    }

步骤2
创建多Item布局公用适配器。

public class MultiTypeAdapter extends RecyclerView.Adapter {
private TypeFactory typeFactory;
private List models;
public MultiTypeAdapter(List models, TypeFactory typeFactory) {
this.models = models;
this.typeFactory = typeFactory;
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = View.inflate(parent.getContext(), viewType, null);
RecyclerView.LayoutParams params = new RecyclerView.LayoutParams(-1, -2);
itemView.setLayoutParams(params);
return typeFactory.createViewHolder(viewType, itemView);
}
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
holder.bindData(models.get(position), position, this);
}
@Override
public int getItemViewType(int position) {
if (null == typeFactory) return -1;
return models.get(position).type(typeFactory);
}
@Override
public int getItemCount() {
return null == models ? 0 : models.size();
}
}

步骤3
根据需求设计创建不同Model和不同ViewHolder以及它们对应的工厂,这里只是Demo的案例。

  1. Model
    public class BannerModel implements Visitable {
    @Override
    public int type(TypeFactory typeFactory) {
    return typeFactory.type(this);
    }
    public List mPath;
    }
    public class HomeListModel implements Visitable {
    @Override
    public int type(TypeFactory typeFactory) {
    return typeFactory.type(this);
    }
    public String username;
    public String birthday;
    public String telnumber;
    public String occupation;
    }
  2. ViewHolder
    public class BannerViewHolder extends BaseViewHolder {
    private final TextView imageView;
    public BannerViewHolder(View itemView) {
    super(itemView);
    imageView = (TextView) itemView.findViewById(R.id.imageView);
    }
    @Override
    public void bindData(BannerModel model, int position, MultiTypeAdapter adapter) {
    //如果这里model是一个
    imageView.setBackgroundResource(R.mipmap.banner1);
    itemView.setBackgroundColor(Color.parseColor(“#ff9900”));
    }
    }
    public class HomeListViewHolder extends BaseViewHolder {
    private SuperTextView mTextView;
    public HomeListViewHolder(View itemView) {
    super(itemView);
    mTextView = (SuperTextView) itemView.findViewById(R.id.super_tv);
    }
    @Override
    public void bindData(HomeListModel model, int position, MultiTypeAdapter adapter) {
    mTextView.setLeftTopString(model.username);
    mTextView.setRightTopString(model.occupation);
    mTextView.setRightBottomString(model.birthday);
    }
    }
    3.Factory
    public class HomeTypeFactory implements TypeFactory {
    public static final int TYPE_RESOURCE_ONE = R.layout.home_banner_item;
    public static final int TYPE_RESOURCE_TWO = R.layout.home_list_item;
    @Override
    public int type(Visitable visitable) {
    if (visitable instanceof BannerModel) {
    return TYPE_RESOURCE_ONE;
    } else if (visitable instanceof HomeListModel) {
    return TYPE_RESOURCE_TWO;
    } else {
    return 0;
    }
    }
    @Override
    public BaseViewHolder createViewHolder(int type, View itemView) {
    if (type == TYPE_RESOURCE_ONE) {
    return new BannerViewHolder(itemView);
    } else if (type == TYPE_RESOURCE_TWO) {
    return new HomeListViewHolder(itemView);
    }
    return null;
    }
    }

步骤4
设置适配器。

mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
LinearLayoutManager lm = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mAdapter = new MultiTypeAdapter(mModels, new HomeTypeFactory());
mRecyclerView.setLayoutManager(lm);
mRecyclerView.setAdapter(mAdapter);

总结
到这里基本实现多布局没问题了,公用适配器,抽象类及接口可以复制。在使用时我们可以创建不同的Model数据源,不同的ViewHolder对象进行数据绑定,在Factory中定义不同布局下的类型及返回不同的ViewHolder即可。
最后附上Demo源码,demo中可能还有其他非相关代码,可以不用管它们。

猜你喜欢

转载自blog.csdn.net/qq_19707091/article/details/77948160
今日推荐