1. 简介
RecyclerView是一种特殊的view,可以用来显示类似列表的数据。
要展示一个RecyclerView,需要的组成成分包括:数据实体类、Adapter类、ViewHolder类以及显示view的Activity/Fragment。
数据实体类定义每一个item中要显示的数据,如字符串、图像等;
Adapter类用来绑定、创建ViewHolder,Activity/Fragment中的recyclerView对象通过设置该adapter实现对item中内容的显示;Adapter类需要继承自RecyclerView.Adapter,重写onCreateViewHolder、onBindViewHolder、getItemCount等方法;
ViewHolder类用来绑定每一个item展示时对应的布局文件及其id;ViewHolder类需要继承自RecyclerView.ViewHolder类。
RecyclerView的简单使用见文章。
2. 多布局分析与效果展示
在一个Fragment中展示包括Banner轮播图、日期TextView以及内容TextView,因此需要展示三种类别的内容。该RecyclerView作为多Tab切换中的首页Tab,其余Tab展示其他View,每一个Tab都是一个Fragment,因此Activity需要用一个容器来承载不同Tab对应的Fragment的布局文件。
MainActivity布局文件设计如下:
1 |
|
其中fl_container这个FrameLayout用来承载不同的Fragment,CommonTabLayout用来展示底部导航。
首页Fragment的布局文件设计如下:
1 |
|
其中最外层的SmartRefreshLayout表示整个区域可刷新, MaterialHeader表示刷新时的头部样式,紧接着的FrameLayout为整个页面需要显示的东西,包括ToolBar和自定义的MultipleStatusView,MultipleStatusView为多种状态下View的显示,包括无网络、加载错误、加载成功等,其中包裹着一个RecyclerView,该RecyclerView即数据加载成功时页面展示的所有内容。
当Activity添加了该Fragment后,展示样式如图所示:

3. 编码实现
(1) activity显示底部导航数据
- 定义底部导航选中与未选中时的图标与文字:
1 | private val mTitles = arrayOf("每日精选", "发现", "热门", "我的") |
- 自定义TabEntity类用于得到图标与文字,该类继承自CustomTabEntity类:
1 | class TabEntity(var title: String, private var selectedIcon: Int, private var unSelectedIcon: Int) : |
- 设置显示的样式
1 | private fun initTab() { |
(2) Acticity获得Fragment实例显示Fragment布局
1 | private fun switchFragment(position: Int) { |
(3) Fragment中RecyclerView状态的改变
当RecyclerView滚动结束后需要判断是否需要加载更多数据,滚动停止后RecyclerView内的childCount返回的是当前可见的view个数,RecyclerView.layoutManager.itemCount返回的是布局中填充的item个数,layoutManager的findFirstVisibleItemPosition方法返回的是布局管理器中可见的第一个View的position,通过三个数值大小判断是否要加载更多数据。
1 | mRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { |
滚动时ToolBar中的字体需要根据当前位置来决定显示什么文字:
当Type为Banner时不显示ToolBar,当Type为日期TextView,更新ToolBar文字为日期TextView的文字;当Type为内容TextView,ToolBar中的文字一直显示日期TextView的文字。
1 | // 滚动时调用 |
(4) 显示不同type的内容
显示的type包括Banner、日期TextView以及内容TextView。每一种type用一个布局文件设计,因此包括三种布局文件。
item_home_banner布局文件设计如下:
1 |
|
该文件仅包含一个Banner,用于显示轮播图。
Item_home_header布局文件设计如下:
1 |
|
该文件仅包含一个TextView,用于显示日期。
item_home_content布局文件设计如下:
1 |
|
该布局文件用于显示每一个content,包括图片、文字、底部线条。
前面提到RecyclerView需要自定义Adapter继承自RecyclerView.Adapter、自定义ViewHolder继承自RecyclerView.ViewHolder。
Adapter类需要继承自RecyclerView.Adapter,重写onCreateViewHolder、onBindViewHolder、getItemCount、getItemViewType方法。
getItemCount返回RecyclerView中item的个数,其中Banner有多张图片,但只算一个item:
1 | /** |
getItemViewType返回RecyclerView中item的类型:
1 | /** |
onCreateViewHolder中根据不同的type得到不同的ViewHolder:
1 | /** |
ViewHolder传入解析的View作为参数,在其中通过set方法对子控件进行赋值,由于子控件包含ImageView、TextView多种View,因此在ViewHolder中定义泛型方法得到View,根据不同的View设置不同内容:
1 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { |
onBindViewHolder是对每一个holder进行数据的绑定,同时调用set方法设置每个ViewHolder中不同view应该展示的内容:
1 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { |