-- 实现类似于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]: http://weibo.com/xiezilailai [2]: http://bbs.anzhuo.cn/thread-982250-1-1.html [3]: http://www.tuicool.com/articles/aeeaQ3J [4]: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0710/1631.html