上一节我们讲到了 Android 5.X新特性之RecyclerView基本解析及无限复用 相信大家也应该熟悉了RecyclerView的基本使用,这一节我们来学习下,为RecyclerView添加HeaderView和FooterView。

针对RecyclerView的头部和底部,官方并没有给我们提供像listView一样可以直接通过addHeaderView()/addFooterView()的方法,所以只能靠我们自己去实现了,那怎么实现呢?大家都知道RecyclerView已经为我们封装好了Adapter和ViewHolder,在Adapter中我们需要重写onCreateViewHolder(ViewGroup parent, int viewType)这个方法方便我们把ItemView布局文件或是自定义View传递到ViewHolder中,从而达到ItemView的重复使用和回收等。而我们今天要讲的添加头部和底部和该方法有密不可分的关系。

大家仔细观察onCreateViewHolder(ViewGroup parent, int viewType)这个方法,在它的参数中,含有一个viewType,它就代表了每一个子列表中的ItemView的类型,而该类型我们又可以通过Adapter中封装好的getItemViewType()方法来定义。因此,我们可以根据这两个方法来完成我们今天的学习。

首先,我们也需要在BaseRecyclerAdapter中添加一个addHeaderView的方法,用于接受Activity中传递过来的HeaderView,并且把HeaderView添加到第0个ItemView中。

	private View mHeaderView;
public void addHeaderView(View headerView){
mHeaderView = headerView;
notifyItemInserted(0);
}

然后,我们在我们自定义的BaseRecyclerAdapter中重写getItemViewType()方法,并且定义两个静态变量来区分我们的viewType的类型,如下:

	public final static int TYPE_HEADER = 0;
public final static int TYPE_BODY = 1;
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}

ok,现在我们可以针对getItemViewType()方法来为我们的ItemView设置viewType类型了。我们知道,getItemViewType()默认返回的是0这个类型,所以我们重载该方法,在没有mHeaderView时,我们让它返回TYPE_BODY这个类型,而当有mHeaderView,由于把它添加到第0个ItemView中了,所以我们可以根据position等于0的时候让它返回TYPE_HEADER这个类型。定义好的类型将会在onCreateViewHolder()中使用到。

所以我们的getItemViewType方法可以这样设计:

	@Override
public int getItemViewType(int position) {
if(mHeaderView == null)
return TYPE_BODY;
if(position == 0) {
return TYPE_HEADER;
}
return TYPE_BODY;
}

到这里大家已经很明确的知道了每个ItemView的viewType类型了,那么我们就可以在onCreateViewHolder()方法中根据ItemView的viewType来做出不同的判断了,如下:

	@Override
public BaseViewHolderHelper onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == TYPE_HEADER && mHeaderView != null){
return new BaseViewHolderHelper(mHeaderView);
}
View view = LayoutInflater.from(parent.getContext()).inflate(mLayoutResId, parent, false);
return new BaseViewHolderHelper(view);
}

代码一目了然,就是根据viewType判断是否为TYPE_HEADER,如果是,则添加不同的布局或View,否则,加载正常的布局,其他的不变。

然后,我们就可以在onBindViewHolder(BaseViewHolderHelper holder, int position)方法中根据当前的position位置来绑定我们要显示数据了。

	@Override
public void onBindViewHolder(BaseViewHolderHelper holder, int position) {
if(getItemViewType(position) == TYPE_HEADER){
return;
}else{
if(mHeaderView != null){
position-- ;
}
holder.itemView.setTag(position);
holder.itemView.setOnClickListener(this);
holder.itemView.setOnLongClickListener(this);
T itemData = mDatas.get(position);
displayContents(holder,itemData);
}
}

代码解释:如果当前position位置的类型是TYPE_HEADER,也就是说用来显示mHeaderView的,这里我们就直接返回mHeaderView的布局,不做事件处理了;如果不是,并且RecyclerView是有带mHeaderView头部的,那么由于它占去第0个itemView,所以我们的position是从第一个开始计算的,所以我们必须得到当前真实position位置,并通过position位置来获取当前的真实数据,如果不带mHeaderView头部,则可直接根据position获取显示数据,其他的逻辑不变。

还有注意的是当mHeaderView不为空时,我们的数据量大小也有一定的变化,请看:

	@Override
public int getItemCount() {
return mHeaderView != null ? mDatas.size() + 1 : mDatas.size();
}

ok,在RecycerActivity的onCreate方法中添加一下两句:

View headerView = LayoutInflater.from(this).inflate(R.layout.item_view1, null);
mBaseRecyclerAdapter.addHeaderView(headerView);

来看看运行结果吧

ok,已经完成了mHeaderView 的添加。但是有个小问题,当你把RecyclerView的布局设置为GridLayoutManager时,如:mRecyclerView.setLayoutManager(new GridLayoutManager(this,2));就会出现这种情况:

这种情况也很好解决,在GridLayoutManager中我们可以在SpanSizeLookup中重新设置显示的列数。

  @Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if(manager instanceof GridLayoutManager){
final GridLayoutManager gridLayoutManager = ((GridLayoutManager) manager);
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
//是HeaderView则占所有列,否则只占自己列
return getItemViewType(position) == TYPE_HEADER ? gridLayoutManager.getSpanCount() : 1;
}
});
}
}

最主要的就是在getSpanSize方法中根据我们的需要重新设置就ok了。看看吧

好了,mHeaderView 已基本搞定,现在来看看怎么添加FooterView了,其实原理是一样的,也是根据getItemViewType()返回的ViewType类型来加载不同的布局了。

首先我们需要定义一个内部类FooterViewHolder继承我们的BaseViewHolderHelper,它主要是用来绑定FooterView布局文件:

	private class FooterViewHolder extends BaseViewHolderHelper{
private TextView footView;
public FooterViewHolder(View itemView) {
super(itemView);
footView = (TextView) itemView.findViewById(R.id.tv_addFooter);
}
}

然后在getItemViewType中获取到最后的ItemView的位置并返回TYPE_FOOTER类型:

 @Override
private View mFooterView;
public final static int TYPE_FOOTER = 2;
...... public int getItemViewType(int position) {
if(position + 1 == getItemCount()){
return TYPE_FOOTER;
}
if(mHeaderView == null)
return TYPE_BODY;
if(position == 0) {
return TYPE_HEADER;
}
return TYPE_BODY;
}

另外在getItemCount()方法中我们因为添加个一个FooterView所以需要在原来的基础上再加 1 ;

	@Override
public int getItemCount() {
return mHeaderView != null ? mDatas.size() + 2 : mDatas.size() + 1;
}

再次在onCreateViewHolder方法中根据类型加载不同的布局文件:

@Override
public BaseViewHolderHelper onCreateViewHolder(ViewGroup parent, int viewType) {
... if(viewType == TYPE_FOOTER){
mFooterView = LayoutInflater.from(mContext).inflate(R.layout.custom_footerview, parent,false);
return new FooterViewHolder(mFooterView);
}
View view = LayoutInflater.from(parent.getContext()).inflate(mLayoutResId, parent, false);
return new BaseViewHolderHelper(view);
}

最后在onBindViewHolder方法中来展示我们的数据吧

	@Override
public void onBindViewHolder(BaseViewHolderHelper holder, int position) {
if(getItemViewType(position) == TYPE_HEADER){
return;
}else if(getItemViewType(position) == TYPE_FOOTER){
FooterViewHolder footViewHolder=(FooterViewHolder)holder;
footViewHolder.footView.setText("上拉加载更多...");
} else{
...
}
}

ok,完成,来看看结果吧

总结下,在给RecyclerView添加HeaderView和FooterView时,只要利用好getItemViewType这个方法,返回相对应的ViewType,并且在onCreateViewHolder方法中根据ViewType类型加载不同的布局就完全可是实现我们的需求了。说起来就是这么简单。好了,今天就讲到这里吧,祝大家学习愉快。

更多资讯请关注微信平台,有博客更新会及时通知。爱学习爱技术。

Android 5.X新特性之为RecyclerView添加HeaderView和FooterView的更多相关文章

  1. Android 5.X新特性之为RecyclerView添加下拉刷新和上拉加载及SwipeRefreshLayout实现原理

    RecyclerView已经写过两篇文章了,分别是Android 5.X新特性之RecyclerView基本解析及无限复用 和 Android 5.X新特性之为RecyclerView添加Header ...

  2. 《Android群英传》读书笔记 (5) 第十一章 搭建云端服务器 + 第十二章 Android 5.X新特性详解 + 第十三章 Android实例提高

    第十一章 搭建云端服务器 该章主要介绍了移动后端服务的概念以及Bmob的使用,比较简单,所以略过不总结. 第十三章 Android实例提高 该章主要介绍了拼图游戏和2048的小项目实例,主要是代码,所 ...

  3. Android 6.0 新特性 整理 资料来自网络

    Android 6.0新特性 Runtime Permissions Doze and App Standby Apache HTTP Client Removal BoringSSL Access ...

  4. 腾讯云安全:开发者必看|Android 8.0 新特性及开发指南

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 背景介绍 谷歌2017 I/O开发者大会今年将于5月17-19日在美国加州举办.大会将跟往年一样发布最新的 A ...

  5. Android 8.0 新特性

    Android 8.0 (Android Oreo(奥利奥))新特性介绍 通知渠道 - Notification Channels 通知渠道是由应用自行定义的通知内容类别,借助渠道,开发者可以让用户对 ...

  6. 开发者必看|Android 8.0 新特性及开发指南

    背景介绍 谷歌2017 I/O开发者大会今年将于5月17-19日在美国加州举办.大会将跟往年一样发布最新的 Android 系统,今年为 Android 8.0.谷歌在今年3 月21日发布 Andro ...

  7. android 7.0 新特性 和对开发者的影响

    android 7.0新特性 - jiabailong的专栏 - 博客频道 - CSDN.NEThttp://blog.csdn.net/jiabailong/article/details/5241 ...

  8. Atitit.android  jsbridge v1新特性

    Atitit.android  jsbridge v1新特性 1. Java代码调用js并传参其实是通过WebView的loadUrl方法去调用的.只是参数url的写法不一样而已1 2. 三.JAVA ...

  9. Android 5.0 新特性

    Material Design Material Design简介 Material Design是谷歌新的设计语言,谷歌希望寄由此来统一各种平台上的用户体验,Material Design的特点是干 ...

随机推荐

  1. 入园记------我的DBA之路

    今天周一拖着疲惫的身躯 11点才离开公司,回到家估计写完这篇博客就要17号了. 一个人走在回家的路上,很黑,突然很多感触,一个人在北京拼搏,不敢停止学习的脚步,因为只要停下来就会感觉到孤独. 回顾一下 ...

  2. python常用模块

    os模块 os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录:相当于shell下cd os ...

  3. MVC5 网站开发之八 栏目功能 添加、修改和删除

    本次实现栏目的浏览.添加.修改和删除. 栏目一共有三种类型. 常规栏目-可以添加子栏目,也可以添加内容模型.当不选择内容模型时,不能添加内容. 单页栏目-栏目只有一个页面,可以设置视图. 链接栏目-栏 ...

  4. ASP.NET MVC5+EF6+EasyUI 后台管理系统(48)-工作流设计-起草新申请

    系列目录 创建新表单之后,我们就可以起草申请了,申请按照严格的表单步骤和分支执行. 起草的同时,我们分解流转的规则中的审批人并保存,具体流程如下 接下来创建DrafContoller控制器,此控制器只 ...

  5. Oracle_创建和管理表

    创建和管理表 常见的数据库对象 Oracle 数据库中的表 查询数据字典 命名规则 CREATE TABLE 语句 数据类型 使用子查询创建表 ALTER TABLE 语句 删除表 清空表 改变对象的 ...

  6. windows下mysql 主从同步

    半路出家到Java,刚开始听说到说程序支持读写分离感觉特别高大上,也一直没接触 偶然的机会接触到了,就一定得记下来. 今天先讲讲数据库的主从同步,两个好处: 一是读写分离可以用上.比如 写操作就写到主 ...

  7. Java Collection知识总结

    首先说说java中常用的集合容器:ArrayList,LinkedList,Vector,HashMap,Hashtable,HashSet,TreeSet.[就个人认为] java集合容器本人理解为 ...

  8. highlight.js 代码高亮插件

    官网:https://highlightjs.org/ API:http://highlightjs.readthedocs.org/en/latest/api.html 1. 简单使用: <l ...

  9. h5engine造轮子

    基于学习的造轮子,这是一个最简单,最基础的一个canvas渲染引擎,通过这个引擎架构,可以很快的学习canvas渲染模式! 地址:https://github.com/RichLiu1023/h5en ...

  10. [JSP]JSP 简介

    1.1 概述 1.1.1 什么是 JSP? JSP 全称是 Java Server Pages,是一种动态网页开发技术. 它与 PHP.ASP.ASP.NET 等语言类似,运行在服务端的语言. JSP ...