带HeaderView和FooterView的自定义RecyclerView.Adapter

来源:互联网 发布:房地产横盘 知乎 编辑:程序博客网 时间:2024/06/08 11:43

– 实现类似于listView中的addHeaderView方法和addFooterView方法


序言

今天要给大家介绍的是自定义的RecyclerView.Adapter,名字叫做 BaseHeadFootAdapter,通过这个Adapter你可以像ListView一样在RecyclerView中直接添加HeaderView和FooterView,你只需要写下面几行代码。

        //MyBaseHeadFootAdapter继承自BaseHeadFootAdapter        adapter=new MyBaseHeadFootAdapter(this,list);        adapter.addHeaderView(headView);        adapter.addFooterView(footView);        recyclerView.setAdapter(adapter);

然后你就可以实现这样的效果

这里写图片描述

使用

如果你只是单纯的想使用,你可以直接点击进入下面的gitHub,你可以看到如何使用它(博客后边其实也有交代),如果你有任何疑问,欢迎关注我的微博同我交流。如果我的项目对你有一丢丢帮助的话,记得star或者follow我哦!

GitHub地址: 自定义HeadFootAdapter
微博:蝎子莱莱的微博

在使用ListView的过程中有两个方法很常用到,那就是ListView中的addHeaderView()和addFooterView(),他们的作用显而易见,那就是在你的listView中添加特殊的两个布局,一个是在顶端,另一个会在底端。如果你没有使用过它们可能会有点好奇,直接把这些布局放在listView上面不就行了吗,为什么非要把它添加到listView里面去呢?

这是因为有这样一种情况我们经常会遇到,下面是京东的一张截图,如果让你去实现这样一个布局你会怎么做呢?
这里写图片描述

你可能会这样做:最外面是一个ScrollView,上面是三张图片那个布局,下面是一个ListView。当然,这样是肯定不行的,你会发现ScrollView和ListView是会滑动冲突的,具体的解决方案你可以看这篇方案

四种方案解决ScrollView嵌套ListView问题

里面提到一种方案和我今天说的很类似,但是不一样,上面说你可以将顶部的布局当成是一种item,因为ListView中的adapter是支持多种type的。但是我个人觉得这种方法并不是很优美,只是一个头部VIew却让你的adapter中代码变得很臃肿,我个人更加倾向于将这个布局放在HeaderView中,你不需要改变adapter中的代码,只需要在Activity中引用添加这个View就好了。

但是RecyclerView的出现是对ListView是一个很大的威胁,RecyclerView上有着太多超越ListView的地方,现在更多是推荐使用RecyclerView,二者的区别这里我们不细讨论,你可以参考下面这篇博客

Android控件RecyclerView和ListView的异同

如果你不是很了解RecyclerView,你可以参考下面这篇博文

RecyclerView:更高级更灵活的ListView

但是RecyclerView也不是完美的,在RecyclerView中很多ListView有的功能它反而没有,比如setOnItemClickListener(),当然这个可以你自己来写,难度并不是很大。还有的就是今天我们要说的addHeaderView()和addFooterView(),所以我自己实现了一个RecyclerView的Adapter,通过这个adapter,你可以像ListView一样 直接使用addHeaderView和addFooterView两个方法。

实现

好了,重点来了,说说代码是如何实现的。其实实现非常简单,聪明的你一定也已经想到了。思路就是,其实在RecyclerView中也是支持Adapter中存在多种type的item的,那么我们可以把HeaderView和FooterView当做两种不同的type,我们要做的事情就是想办法将其封装起来,当在项目中使用时,你根本不会感觉到它们的存在,你要做的只是添加addHeaderView()或者addFooterView()而已。

BaseHeadFootAdapter是一个抽象类,你需要继承它并且实现它的几个函数就可以了,这几个函数基本和RecyclerView.Adapter一毛一样(我本来就是做的一点封装)

 /**     * 将头部布局返回到用户继承之后的子类中,     *     * 用户可以这个方法里得到headerVIew,对其进行操作     *     * 比如说headerView中的各种点击事件以及headerView中各种控件的获取     *     *     * @param headerView     */    protected abstract void onBindHeaderView(View headerView);    /**     * 将尾部布局返回到用户继承之后的子类中,     *     * 用户可以这个方法里得到footerVIew,对其进行操作     *     * 比如说headerView中的各种点击事件以及headerView中各种控件的获取     *     *     * @param footerView     */    protected abstract void onBindFooterView(View footerView);    /**     * 获取子类中item的个数     * @return     */    protected abstract int getItemNum();    /**     * 子类需继承的方法之一,和onBindViewHolder方法是一样的     *     * 在这里我进行了封装     *     *     * @param holder     * @param position     */    protected abstract void onBindView(RecyclerView.ViewHolder holder, int position);    /**     * 子类需继承的方法之一,和onCreateViewHolder一样     *     * 这里只是进行了封装     *     *     * @param parent     * @param viewType     * @return     */    protected abstract RecyclerView.ViewHolder onCreateHolder(ViewGroup parent, int viewType);

仔细看着几个方法,其实getItemNum()就是RecyclerView.Adapter
中的getItemCount(),onBindView(···)就是onBindViewHolder(···),
getViewType()就是getItemViewType(),这三个方法也是继承Adapter必须要实现的方法。而另外两个onBindHeaderView(View headerView),onBindFooterView(View footerView)是之前没有的,用户可以在这两个方法中获取自己设置的headerView或者footerView,并且使用它们(比如设置点击事件或者设置view中控件的值)

前面提到的我在这个类中做了封装,这里我们拿onCreateViewHolder举例,看下面的代码

 @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {       if(viewType==HEAD_TYPE){           return  new HeadFooterViewHolder(headerView);       }else if(viewType==FOOT_TYPE){           return new HeadFooterViewHolder(footerView);       }else //如果不是头布局和尾部局,那么就使用子类中的onCreateHolder方法中指定的ViewHolder           return onCreateHolder(parent, viewType);    }

其实你就会很清楚,如果是HeaderView我就创建HeaderView的viewHolder,如果是普通的item就使用用户实现的onCreateHolder(···)来创建,因为这个方法是个虚函数,是用户实现的。其他的两个方法也是同样的道理分装起来的,我就不再赘述,感兴趣的话你可以查看我的源码。

使用

使用起来的话也非常简单,你只需要将我的BaseHeadFootAdapter类拷贝的你项目中,并且继承它实现它的几个方法即可。和你使用原生的RecyclerView.Adapter是完全一样的,你的item也可以有多种type,但是要记得type值不要是-100和-101(已经被HeaderView和FooterView占用了)。最后你只需在你自己的Adapter中调用方法即可。

        adapter.addHeaderView(headView);        adapter.addFooterView(footView);

这样你就可以在你的Adapter(继承自BaseHeadFootAdapter)中对header和FooterView进行操作,下面以HeaderView为例

 @Override    protected void onBindHeaderView(View headerView) {        headerView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Toast.makeText(context,"head was clicked",Toast.LENGTH_SHORT).show();            }        });    }

其实,只要你掌握了RecyclerView的基本用法很快就可以使用这个自定义的Adapter,我gitHub中那个project是一个使用了这个Adapter的例子,你可以参考一下,其中MyBaseHeadFootAdapter是继承自BaseHeadFootAdapter的Adapter类,MyViewHolder是item的viewHolder(和RecyclerView的标准写法是一样的)。
最后,还是将github和我的微博贴出来,欢迎大家和我交流学习。谢谢!

GitHub地址: 自定义HeadFootAdapter
微博:蝎子莱莱的微博

1 0
原创粉丝点击