RecyclerView中添加通用FooterView和HeaderView

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_23179075/article/details/78984197

请注明出处:http://blog.csdn.net/qq_23179075/article/details/78984197

RecyclerView中添加通用FooterView和HeaderView

都知道 ListView提供了 addFooterView()addHeaderView() 两个方法来给列表添加 底部头部 的布局,但是现在很多应用中都放弃了 ListView 这个控件从而选择 RecyclerView 这个强大的控件,RecyclerView 的强大主要在于它的高度灵活性。存在于 ListView 中的一些常用的功能,在 RecyclerView 中都需要程序员自己实现。比如:item 的点击事件、item 的分割线等等。

RecyclerView 中实现 FooterViewHeaderView 方式有多种,这里仅代表个人实现方法。

本文主要讲在 RecyclerView 中添加 FooterView , 因为 HeaderView 实现方式都大同小异,就不用赘述了。

先看效果

这里写图片描述
上图的 点击刷新 就是本文所添加的 FooterView,底部布局很简单,当然底部什么样子都是根据需求来定。

下面上图的实现代码讲解。本文主要是通过自定义 Adapter 的方式来实现的。主要的核心是,实现父类 RecyclerView.Adapter<>getItemViewType(int position)。通过这个方法我们可以为每个 item 设置一个 Type

@Override
public int getItemViewType(int position) {
    //将list的最后一个item的Type设置为footer,其余的都设置成正常显示,
    //如果有HeaderView,可以将第一个设置为 header
    if (position == getItemCount() - 1) {
        return TYPE_FOOTER;
    }
    return TYPE_NORMAL;
}

onCreateViewHolder(ViewGroup parent, int viewType) 的是实现方法中通过这个 Type ,来判断当前item来创建相应的 ViewHolder

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    //通过判断item的类型,创建对应的ViewHolder
    if (viewType == TYPE_FOOTER) {
        //加载footer的ViewHolder
        return footerViewHolder(parent);
    }
    //加载item的ViewHolder
    return itemViewHolder(parent);
}

当然在 onBindViewHolder(RecyclerView.ViewHolder holder, int position) 中也需要通过 itmeType 来绑定对应的 Holoder

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    int viewType = getItemViewType(position);
    //通过判断item的类型,绑定不同的ViewHolder
    if (viewType == TYPE_NORMAL) {
        onBindItemViewHolder((IVH) holder,position);
    }else {
        onBindFooterViewHolder((FVH) holder,position);
    }
}

本文在这里是实现了一个抽象的 BaseFooterAdapter 类,如果需求中有 FooterView ,就可以继承该类来实现,下面是这个类的所有代码:

/**
 * @author zhengliang
 * @data   2018/1/5.
 * 这里通过范型的方式传入 Item和Footer的ViewHolder的实现类
 */
public abstract class BaseFooterAdapter<IVH extends RecyclerView.ViewHolder,FVH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    /**
     * 说明是带有Footer的
     */
    private static final int TYPE_FOOTER = 1;
    /**
     * 正常的item
     */
    private static final int TYPE_NORMAL = 2;
    /**
     * item点击事件
     */
    protected OnItemViewClickListener itemListener;
    /**
     * footer中的点击事件
     */
    protected OnItemViewClickListener footerListener;

    @Override
    public int getItemViewType(int position) {
        //将list的最后一个item的Type设置为footer;
        if (position == getItemCount() - 1) {
            return TYPE_FOOTER;
        }
        return TYPE_NORMAL;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //通过判断item的类型,创建对应的ViewHolder
        if (viewType == TYPE_FOOTER) {
            //加载footer
            return footerViewHolder(parent);
        }
        return itemViewHolder(parent);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        int viewType = getItemViewType(position);
        //通过判断item的类型,绑定不同的ViewHolder
        if (viewType == TYPE_NORMAL) {
            onBindItemViewHolder((IVH) holder,position);
        }else {
            onBindFooterViewHolder((FVH) holder,position);
        }
    }

    @Override
    public int getItemCount() {
        //因为最后一个item是Footer,所以要+1
        return getItemCountSize()+1;
    }

    /**
     * 子类实现列表的大小
     * @return
     */
    public abstract int getItemCountSize();

    /**
     * item布局实现
     * @param parent
     * @return
     */
    public abstract IVH itemViewHolder(ViewGroup parent);

    /**
     * 底部布局实现
     * @param parent
     * @return
     */
    public abstract FVH footerViewHolder(ViewGroup parent);

    /**
     * 绑定item
     * @param holder
     * @param position
     */
    public abstract void onBindItemViewHolder(IVH holder, int position);

    /**
     * 绑定footer
     * @param holder
     * @param position
     */
    public abstract void onBindFooterViewHolder(FVH holder, int position);

    public void setItemViewClickListener(OnItemViewClickListener listener) {
        this.itemListener = listener;
    }

    public void setFooterListener(OnItemViewClickListener footerListener) {
        this.footerListener = footerListener;
    }
    /**
     * date 2017/8/9
     * @author zhengliang
     * 自定义点击事件
     */
    public interface OnItemViewClickListener {
        /**
         * 单击事件
         *
         * @param view     控件
         * @param position 位置
         */
        void onClick(View view, int position);
    }
}

代码就不逐句讲解,相信注释都能明白。如果需要 HeaderView 就在泛型中加 HeaderViweHolder ,然后对应处理下 HeaderViewType 就行了,都是和 HeaderView 一样一样的。

接下来看看如果使用

/**
 * @author zhengliang
 */
public class ItemTaskListAdapter extends BaseFooterAdapter<ItemTaskListAdapter.MyItemViewHolder,ItemTaskListAdapter.MyFooterViewHolder> {

    private Context context;

    private List<TaskListResp.ContentBean> taskList;


    public ItemTaskListAdapter(Context context) {
        this.context = context;
        this.taskList = new ArrayList<>();
    }

    public void addAll(List<TaskListResp.ContentBean> taskList) {
        this.taskList = taskList;
        this.notifyDataSetChanged();
    }

    @Override
    public int getItemCountSize() {
        return taskList.size();
    }

    @Override
    public MyItemViewHolder itemViewHolder(ViewGroup parent) {
        return new MyItemViewHolder(LayoutInflater.from(context).inflate(R.layout.item_task, parent, false));
    }

    @Override
    public MyFooterViewHolder footerViewHolder(ViewGroup parent) {
        return new MyFooterViewHolder(LayoutInflater.from(context).inflate(R.layout.layout_footer_refresh, parent, false));
    }

    @SuppressLint("SetTextI18n")
    @Override
    public void onBindItemViewHolder(MyItemViewHolder holder, int position) {
        TaskListResp.ContentBean task = taskList.get(position);
        holder.tvTitle.setText(task.getTitle());
        holder.tvDescription.setText(task.getDescription());
        holder.tvTime.setText(DateUtils.stampFormatTime(task.getEntryDt(), "yyyy-MM-dd HH:mm"));
        if (super.itemListener != null) {
            holder.root.setOnClickListener(v -> super.itemListener.onClick(v, position));
        }

    }

    @Override
    public void onBindFooterViewHolder(MyFooterViewHolder holder, int position) {
        if (super.footerListener != null) {
            holder.rvFooter.setOnClickListener(v -> super.footerListener.onClick(v, position));
        }
    }

    class MyItemViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.root)
        RelativeLayout root;
        @BindView(R.id.iv_img)
        ImageView ivImg;
        @BindView(R.id.tv_title)
        TextView tvTitle;
        @BindView(R.id.tv_description)
        TextView tvDescription;
        @BindView(R.id.tv_time)
        TextView tvTime;
        @BindView(R.id.iv_enter)
        ImageView ivEnter;

        MyItemViewHolder(View view) {
            super(view);
            ButterKnife.bind(this, view);
        }
    }

    class MyFooterViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.rv_footer)
        RelativeLayout rvFooter;
        MyFooterViewHolder(View footerView) {
            super(footerView);
            ButterKnife.bind(this, footerView);
        }
    }
}

只要对应实现 BaserFooterAdapter 的抽象方法就行了,跟之前使用 Adapter 一样。

猜你喜欢

转载自blog.csdn.net/qq_23179075/article/details/78984197