一个简单的自定义RecyclerView适配器(六)——多布局

实体类

创建一个多布局基类BaseMultiItemEntity

public class BaseMultiItemEntity {

    private int itemType;

    public BaseMultiItemEntity(@LayoutRes int itemType) {
        this.itemType = itemType;
    }

    public int getItemType() {
        return itemType;
    }

    public void setItemType(@LayoutRes int itemType) {
        this.itemType = itemType;
    }
}

多布局实体类必须继承BaseMultiItemEntity

public class MultiItemEntity extends BaseMultiItemEntity {

    private String name;
    private String pass;

    public MultiItemEntity(int itemType, String name, String pass) {
        super(itemType);
        this.name = name;
        this.pass = pass;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPass() {
        return pass;
    }

    public void setPass(String pass) {
        this.pass = pass;
    }
}

多布局适配器

public abstract class BaseMultiItemAdapter  extends BaseRecyclerViewAdapter{

    public BaseMultiItemAdapter(@Nullable List data) {
        super(data);
    }

    @Override
    public int getItemViewType(int position) {
        return data.get(position).getItemType();
    }
}

在BaseRecyclerViewAdapter添加以下代码

//是否是多布局
private boolean isMultiItem = false;

/**
 * 单布局构造函数
 * @param resource 布局文件
 * @param data item数据
 */
public BaseRecyclerViewAdapter(@LayoutRes int resource, @Nullable List data){
    this.data = data == null ? new ArrayList() : data;
    if (resource != 0) {
        this.resource = resource;
        isMultiItem = false;
    }
}

/**
 * 多布局的类型
 */
private SparseIntArray layouts;
private int getLayoutId(@LayoutRes int viewType) {
    return layouts.get(viewType);
}

/**
 * 多布局构造函数
 * @param data item数据
 */
protected BaseRecyclerViewAdapter(@Nullable List data) {
    this(0, data);
    isMultiItem = true;
    layouts = new SparseIntArray();
    baseMultiItemEntities = (List) data;
    if (baseMultiItemEntities != null) {
        for (BaseMultiItemEntity t :baseMultiItemEntities){
            layouts.put(t.getItemType(), t.getItemType());
        }
    }
}

修改BaseRecyclerViewAdapter的onCreateViewHolder方法

@NonNull
@Override
public K onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {

    context = viewGroup.getContext();
    Application application = (Application) context.getApplicationContext();

    View view;
    LayoutInflater mLayoutInflater = LayoutInflater.from(context);
    if (isMultiItem){
        view = mLayoutInflater.inflate(getLayoutId(viewType), viewGroup, false);
    }else {
        view = mLayoutInflater.inflate(resource, viewGroup, false);
    }

    K baseViewHolder = createBaseViewHolder(view);

    bindViewClickListener(baseViewHolder);
    baseViewHolder.setAdapter(this, application);
    return baseViewHolder;
}

使用

在Activity中

val list = ArrayList()
list.add(MultiItemEntity(R.layout.item,"12","34"))
list.add(MultiItemEntity(R.layout.item2,"12","34"))
list.add(MultiItemEntity(R.layout.item,"12","34"))
val adapter = MultiItemAdapter(list)

recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter

适配器

public class MultiItemAdapter extends BaseMultiItemAdapter {

    public MultiItemAdapter(@Nullable List data) {
        super(data);
    }

    @Override
    public void convert(@NonNull BaseViewHolder holder, MultiItemEntity item, int position) {
        switch (holder.getItemViewType()){
            case R.layout.item:
                holder.setText(R.id.textView2,item.getName()+item.getPass());
                holder.addOnClickListener(R.id.imageView).addOnLongClickListener(R.id.imageView);
                holder.addOnClickListener(R.id.textView2).addOnLongClickListener(R.id.textView2);
                break;
            case R.layout.item2:
                holder.setText(R.id.textView,item.getName()+item.getPass())
                        .setText(R.id.textView2,item.getName())
                        .addOnClickListener(R.id.imageView).addOnLongClickListener(R.id.imageView)
                        .addOnClickListener(R.id.textView2).addOnLongClickListener(R.id.textView2)
                        .addOnClickListener(R.id.textView).addOnLongClickListener(R.id.textView);
                break;
        }
    }
}

数据更新

在数据更新时会使用这样一个方法,这个方法在一般的时候是没有问题的。

/**
 * 在列表最后添加一个item
 * @param element item的数据
 */
public void addNewItem(@NonNull T element) {
    data.add(element);
    notifyItemInserted(data.size());
    compatibilityDataSizeChanged(1);
}

但如果添加的是一个新的布局,调用这个方法是会报错的,因为找不到该类型

adapter.addNewItem(MultiItemEntity(R.layout.item3,"12","34"))

有什么办法解决这个问题呢,有两种方式

方式一:
更新数据前调用以下方法添加新布局

/**
 * 添加新布局
 * @param viewType 新布局
 */
public void setLayouts(@LayoutRes int viewType){
    layouts.put(viewType,viewType);
}

方式二:
在更新数据前判断是不是多布局,再判断是不是新布局

/**
 * 是否是新布局
 * @param element BaseMultiItemEntity
 */
public void isNewLayout(@NonNull T element){
    if (isMultiItem){
        int itemType = ((BaseMultiItemEntity) element).getItemType();
        if (getLayoutId(itemType) == 0 ){
            layouts.put(itemType,itemType);
        }
    }
}

/**
 * 是否是新布局
 * @param newData BaseMultiItemEntity集合
 */
private void isNewLayout(@NonNull Collection newData){
    if (isMultiItem){
        for (T element :newData){
            int itemType = ((BaseMultiItemEntity) element).getItemType();
            if (getLayoutId(itemType) == 0 ){
                layouts.put(itemType,itemType);
            }
        }
    }
}

/**
 * 在列表最后添加一个item
 * @param element item的数据
 */
public void addNewItem(@NonNull T element) {
    isNewLayout(element);
    data.add(element);
    notifyItemInserted(data.size());
    compatibilityDataSizeChanged(1);
}

/**
 * 在指定位置添加一个item,如果position越界则添加到列表最后
 * @param position item添加的位置
 * @param element item的数据
 */
public void addNewItem(@IntRange(from = 0) int position,@NonNull T element) {
    if (position < data.size()){
        isNewLayout(element);
        data.add(position, element);
        //更新数据集用notifyItemInserted(position)与notifyItemRemoved(position) 否则没有动画效果。
        //首个Item位置做增加操作
        notifyItemInserted(position);
        compatibilityDataSizeChanged(1);
    }else {
        addNewItem(element);
    }
}

/**
 * 在指定位置添加多个item,如果position越界则添加到列表最后
 * 示例:mAdapter.addData(1, listOf(Person("xin","1"),Person("xin","2")))
 * @param position 插入位置
 * @param newData 多个item的集合
 */
public void addNewData(@IntRange(from = 0) int position, @NonNull Collection newData) {
    if (position < data.size()){
        isNewLayout(newData);
        data.addAll(position, newData);
        notifyItemRangeInserted(position, newData.size());
        compatibilityDataSizeChanged(newData.size());
    }else {
        addNewData(newData);
    }
}

/**
 * 在列表最后添加多个item
 * 示例:mAdapter.addData(listOf(Person("xin","1"),Person("xin","2")))
 * @param newData 多个item的集合
 */
public void addNewData(@NonNull Collection newData) {
    isNewLayout(newData);
    data.addAll(newData);
    notifyItemRangeInserted(data.size() - newData.size() , newData.size());
    compatibilityDataSizeChanged(newData.size());
}

/**
 * 删除一个指定位置的item,如果position越界则无效
 * @param position 指定item的位置
 */
public void removeItem(@IntRange(from = 0) int position) {
    if (position < data.size()){
        data.remove(position);
        notifyItemRemoved(position);
        compatibilityDataSizeChanged(0);
        notifyItemRangeChanged(position, data.size() - position);
    }
}

/**
 * 修改某个item的数据,如果position越界则无效
 * @param position item位置
 * @param element 要修改的item数据
 */
public void replaceItem(@IntRange(from = 0) int position, @NonNull T element) {
    if (position < data.size()){
        isNewLayout(element);
        data.set(position, element);
        notifyItemChanged(position);
    }
}

/**
 * 修改所有item的数据
 * @param newData 更新item数据的集合
 */
public void replaceData(@NonNull Collection newData) {
    // 不是同一个引用才清空列表
    if (newData != data) {
        isNewLayout(newData);
        data.clear();
        data.addAll(newData);
    }
    notifyDataSetChanged();
}

你可能感兴趣的:(安卓基础)