原文链接:https://developer.android.com/guide/topics/ui/layout/recyclerview

用RecyclerView来创建列表视图

如果你的应用需要显示一个滚动的列表视图,并且这个列表包含了大量数据(或一些频繁更改的数据,则可以按照本篇文章的指引来使用RecyclerView。

如果你想创建一个卡片列表,如图2 所示,你也可以使用CardView组件,具体用法参见

创建基于卡片的布局.

如果想查看RecylerView的使用示例代码,参见 RecyclerView Sample App.

RecyclerView 概述

RecyclerView 控件 是ListView 的升级版,更加高级和灵活。
在RecyclerView模型中,会有几个不同的组件配合工作来显示数据。添加到布局中的RecyclerView对象充当构成用户界面的容器。 RecyclerView会使用你设置的布局管理器提供的视图来填充自己的视图。你可以使用系统提供的标准布局管理器(例如LinearLayoutManagerGridLayoutManager),或者实现你自己的布局管理器。

列表中的View组件由ViewHolder(view组件持有者)来表示。你可以继承RecyclerView.ViewHolder 类来创建一个ViewHolder。每个ViewHolder负责显示单个Item的视图。举个例子来说,如果你的列表显示用户的音乐收藏,那每个view holder可能代表的是一个专辑。 RecyclerView只会创建那些需要在屏幕上显示内容的view holder及额外少量的view holder。当用户滚动浏览列表时,RecyclerView会取出未在屏幕上显示的view,并将它们和滚动到屏幕上需要进行显示的数据进行绑定。

view holder(视图持有者)对象由一个adapter(适配器)管理,该适配器通过继承RecyclerView.Adapter创建。adapter根据需要创建view holder。adapter还负责将view holder 和数据进行绑定。它通过将view holder分配给某个位置并调用适配器的onBindViewHolder()方法来完成此操作。这个方法利用view holder 的位置并根据它在列表中的位置来显示内容。

这个RecyclerView模型做了很多优化工作,所以你不必:

  • 当列表首次填充时,它会在列表任一侧创建并绑定一些view holder。例如,如果视图正在显示列表位置0到9,RecyclerView会创建并绑定这些view holder,并且还可能创建并绑定位置10的view holder。这样,如果用户滚动列表,则下一个元素已经提前准备好了。

  • 当用户滚动列表时,RecyclerView根据需要创建新的view holder。它还可以保存已经滚动到屏幕外的view holder,让他们能被重复使用。如果用户变换了滚动方向,那么之前已经滚动出屏幕的view holder就可以拿回来重用。另一方面,如果用户保持相同方向来滚动,那么已经离开最久的view holder可以被重新绑定到新数据。view holder不需要再次执行创建或构造view 的过程,只需要更新view的内容即可。

  • 当显示的item数据发生变化时,你可以通过调用合适的RecyclerView.Adapter.notify ...()方法来通知适配器。之后适配器的内部代码逻辑会自己重新绑定受影响的item。

添加support library

要使用 RecyclerView 控件,你要在项目添加 v7 Support Libraries 依赖。

  1. 打开 module 的build.gradle 文件
  2. dependencies 节点下 添加:
dependencies {implementation 'com.android.support:recyclerview-v7:27.1.1'
}

在布局文件添加 RecyclerView

之后,你就可以在布局文件中添加RecyclerView 了。下面的这个布局把RecyclerView 作为了整个布局的唯一view。

<?xml version="1.0" encoding="utf-8"?>
<!-- A RecyclerView with some commonly used attributes -->
<android.support.v7.widget.RecyclerView
    android:id="@+id/my_recycler_view"android:scrollbars="vertical"android:layout_width="match_parent"android:layout_height="match_parent"/>

然后你就在代码中来操作RecyclerView 了,获取它的引用,设置一个布局管理器,并给需要显示的数据来添加一个adapter 。过程如下:

public class MyActivity extends Activity {private RecyclerView mRecyclerView;private RecyclerView.Adapter mAdapter;private RecyclerView.LayoutManager mLayoutManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.my_activity);mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);// use this setting to improve performance if you know that changes// in content do not change the layout size of the RecyclerViewmRecyclerView.setHasFixedSize(true);// use a linear layout managermLayoutManager = new LinearLayoutManager(this);mRecyclerView.setLayoutManager(mLayoutManager);// specify an adapter (see also next example)mAdapter = new MyAdapter(myDataset);mRecyclerView.setAdapter(mAdapter);}// ...
}

添加列表adapter

要把数据填充到list中去,你需要继承 RecyclerView.Adapter 类。此对象负责为列表项创建视图,并在原始列表项不再可见时用新数据替换某些视图的内容。下面的代码示例实现了一个包含字符串数组的列表,并用TextView 组件显示出来。


public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {private String[] mDataset;// Provide a reference to the views for each data item// Complex data items may need more than one view per item, and// you provide access to all the views for a data item in a view holderpublic static class ViewHolder extends RecyclerView.ViewHolder {// each data item is just a string in this casepublic TextView mTextView;public ViewHolder(TextView v) {super(v);mTextView = v;}}// Provide a suitable constructor (depends on the kind of dataset)public MyAdapter(String[] myDataset) {mDataset = myDataset;}// Create new views (invoked by the layout manager)@Overridepublic MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {// create a new viewTextView v = (TextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.my_text_view, parent, false);...ViewHolder vh = new ViewHolder(v);return vh;}// Replace the contents of a view (invoked by the layout manager)@Overridepublic void onBindViewHolder(ViewHolder holder, int position) {// - get element from your dataset at this position// - replace the contents of the view with that elementholder.mTextView.setText(mDataset[position]);}// Return the size of your dataset (invoked by the layout manager)@Overridepublic int getItemCount() {return mDataset.length;}
}

布局管理器调用适配器的onCreateViewHolder()方法。该方法需要构建一个RecyclerView.ViewHolder并设置其用于显示内容的视图。 ViewHolder的类型必须与Adapter类签名中声明的类型相匹配。通常,它会通过加载XML布局文件来设置视图。由于view holder尚未分配给任何特定的数据,因此该方法实际上并未设置视图的内容。

布局管理器然后将view holder绑定到对应的数据。它通过调用适配器的onBindViewHolder()方法并在RecyclerView中传递view holder的位置来完成此操作。 onBindViewHolder()方法需要获取适当的数据,并用它来填充view holder的布局。例如,如果RecyclerView显示一个名称列表,该方法可能会在列表中找到适当的名称,并填入view holder的TextView控件中。

如果列表需要更新,则调用RecyclerView.Adapter对象的通知方法,例如notifyItemChanged()。布局管理器然后会重新绑定任何受影响的view holder,让他们更新数据。

自定义你的RecyclerView

你可以自定义RecyclerView对象来满足特定需求。标准类已经提供了大多数开发人员需要的所有功能;在许多情况下,你需要做的唯一定制就是为每个view holder设计视图,并编写代码用合适的数据来更新这些视图。但是,如果你的应用程序需求特殊,则可以通过多种方式修改标准行为。以下各节介绍其他一些常用自定义设置。

修改布局

RecyclerView使用布局管理器将各个列表项放置在屏幕上,并确定何时重用对用户不再可见的列表项view视图。要重用(或回收)view,布局管理器可能会请求适配器使用数据集当中的不同元素来替换视图的内容。通过避免创建不必要的视图或执行代价高昂的findViewById()查找方法重用视图提升了性能。 Android支持库包含三个标准布局管理器,每个管理器都提供了许多自定义选项:

  • LinearLayoutManager将项目排列在一维列表中。在LinearLayoutManager中使用RecyclerView提供了像早期ListView布局一样的功能。

  • GridLayoutManager将项目排列在二维网格中,例如棋盘上的方格。在GridLayoutManager中使用RecyclerView提供了像旧版GridView布局一样的功能。

  • StaggeredGridLayoutManager将项目排列在一个二维网格中,每列与之前的一列略有偏移,就像美国国旗中的星星一样。
    如果这些布局管理器都不符合你的需求,则可以通过扩展RecyclerView.LayoutManager抽象类来创建自己的布局管理器 。

添加item动画

每当item发生变化时,RecyclerView会使用 一个animator来改变其外观。这个animator 对象继承自RecyclerView.ItemAnimator类。默认情况下,RecyclerView使用DefaultItemAnimator来提供动画。如果你想提供自定义动画,你可以通过继承RecyclerView.ItemAnimator来定义你自己的animator 对象。

启用列表项选择

recyclerview-selection 库让用户能够使用触摸操作或鼠标操作来选择RecyclerView列表项。你可以自定义选定列表项时的视觉呈现效果。你也可以自定义选取策略,例如哪些列表项可以被选择以及可以选择的列表项数量。

要将RecyclerView,请按照下列步骤操作:

1. 确定要使用哪种选择键类型,然后构建一个ItemKeyProvider

有三种关键类型可用于标识选定项目:Parcelable(以及Uri等所有子类),StringLong。有关选择键类型的详细信息,请参阅SelectionTracker.Builder

2. 实现ItemDetailsLookup 接口。

ItemDetailsLookup使选择库可以访问给定MotionEvent的RecyclerView 列表项的信息。它实际上是一个ItemDetails实例的工厂,它是RecyclerView.ViewHolder的一个实例拷贝(或从中一个实例中提取而来)。

3. 更新RecyclerView中的列表视图以反映用户已选择或取消选择

selection library不提供所选项目的默认视觉效果。当你实现onBindViewHolder()时你必须提供这个。推荐的方法如下:
* 在onBindViewHolder()中,使用truefalse(取决于是否选择该列表项),在View对象上调用setActivated()(而不是setSelected())。
* 更新视图的样式来表示激活的状态。我们建议您使用 color state list resource(颜色状态列表)资源来配置样式。

4. 使用ActionMode给用户提供工具来执行选取操作。

注册一个SelectionTracker.SelectionObserver以在选择更改时通知。首次创建选择时,启动ActionMode将其表示给用户,并提供特定于选择的操作。例如,您可以向ActionMode栏添加一个删除按钮,并连接栏上的后退箭头以清除选择。当选择变为空时(如果用户上次清除选择),不要忘记终止操作模式。

5. 监听选取操作

在结束处理事件序列时,此库可以确定用户是试图通过点击它来激活列表项,还是试图拖放一个或一组选定的列表项。通过注册适当的监听器来监听操作。更多信息请参见SelectionTracker.Builder

6. 使用SelectionTracker.Builder 构造器

以下示例展示了如何利用构造器 采取Long选择键将多个操作组合在一起:

SelectionTracker tracker = new SelectionTracker.Builder<>("my-selection-id",recyclerView,new StableIdKeyProvider(recyclerView),new MyDetailsLookup(recyclerView),StorageStrategy.createLongStorage()).withOnItemActivatedListener(myItemActivatedListener).build();

为了构建SelectionTracker实例,你的应用程序必须给SelectionTracker.Builder提供用于初始化RecyclerView 的那个 RecyclerView.Adapter 。因此,你可以在RecyclerView.Adapter 中 注入一个 SelectionTracker 实例,在adapter 初始化时 初始化这个实例。否则,你无法通过onBindViewHolder()方法检查列表项的选定状态。

7. 在Activity 生命周期事件保持选择状态。

为了在整个Activity生命周期事件中保持选择状态,你的应用程序必须在Activity的onSaveInstanceState()onRestoreInstanceState()方法调用 selection tracker的onSaveInstanceState()onRestoreInstanceState()方法。你的应用程序还必须为SelectionTracker.Builder构造函数提供唯一的选择标识。此ID是必需的,因为Activity或Fragment可能有多个不同的可选列表,所有这些列表都需要保存在其saved state中。

深入RecyclerView(一)相关推荐

  1. Android RecyclerView(和SnapHelper) 实现类似ViewPager的效果

    实现的效果图如下 2 行代码就实现了,其余的都是recyclerview 的代码 如果不显示一次可以滑动多个的话可以使用LinearSnapHelper 具体代码如下(实际就2行代码呢) recycl ...

  2. android RecyclerView 添加可拖动的滚动条

    实现的效果图如下,为了效果这里我设置的宽了一些,实际根据需求修改即可 先说几个属性: android:scrollbars" 一般都是垂直的滚动条设置vertical android:scr ...

  3. RecyclerView 判断滑动到顶部和底部

    可以使用系统提供的 canScrollVertically 方法来判断 具体如下 recycler_view.addOnScrollListener(new RecyclerView.OnScroll ...

  4. RecyclerView 刷新的时候出现阴影的处理方法

    这个阴影是RecyclerView 的问题引起的 处理方法如下 recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER); 这样阴影就消失了.

  5. RecyclerView 删除Item 以及删除整个RecyclerView

    学而时习之,温故而知新. 今天用到了,居然忘记了,好尴尬,这里深夜了也在记录下, 1 删除整个RecyclerView hisList.clear();hisAdapter.notifyDataSet ...

  6. 2个RecyclerView 联动

    看下效果图, 底部在给出demo地址 如果想实现类似拼多多的商品联动也是可以的,修改方法即可 下面看下实现方法 几个参数需要知道 findFirstVisibleItemPosition 显示界面第一 ...

  7. RecyclerView 滑动显示返回按钮,点击返回到顶部

    底部有demo 地址*************************** 需要提前知道一些只是 RecyclerView.SCROLL_STATE_IDLE 是RecyclerView 滑动停止状态 ...

  8. RecyclerView smoothScrollToPosition 和 scrollToPosition 的区别

    smoothScrollToPosition  是平衡的滑动 , 假如现在返回首页 recyclerView.smoothScrollToPosition(0); 看下效果图 scrollToPosi ...

  9. RecyclerView 的findFirstVisibleItemPosition()与findLastVisibleItemPosition()

    findFirstVisibleItemPosition 显示界面的第一个位置 findLastVisibleItemPosition 显示界面最后一个位置 画一个图来说下把 一个横向的Recycle ...

  10. Binary XML file line #8: Error inflating class android.support.v7.widget.RecyclerView

    今天创建了一个 demo ,然后就是复制RecyclerView 过去, 到最后完成运行的时候发现 系统奔溃了, 然后 提示 Binary XML file line #8: Error inflat ...

最新文章

  1. 使用Tape和Vue Test Utils编写快速的Vue单元测试
  2. 搭建MyBatis操作数据库
  3. 大牛书单 | 云原生技术领域好书推荐
  4. zabbix通过JMX监控Tomcat及一些报错
  5. 计算机基础八进制和十六进制试题,计算机基础知识考试试题
  6. Java中equals()方法和==的区别分析
  7. 用python做逻辑回归_python实现逻辑回归
  8. php fpm 日志记录,使用Nginx在PHP-FPM 7上启用错误日志记录?
  9. c语言 变参函数的使用方法,c语言变参函数的vsprintf与va_list的用法
  10. 非标准硬件控制之增加系统API
  11. 销售数据可视化图表excel模板_两份办公学习资源,可视化EXCEL模板和Excel函数课程...
  12. win10隐藏网络计算机,Win10怎么连接隐藏的wifi?
  13. Machine Learning Regression-Case Study
  14. Matlab中set函数
  15. 2022年河南省焊工高级技师理论知识模拟试题及答案
  16. java jsoup 网络爬虫 jsoup解析html Java爬虫 Jsoup爬虫 jsoup例子
  17. webpack.base.conf.js文件
  18. 做一只跑过灰狼的兔子
  19. 带信号灯的最短路dijkstra问题(阿里巴巴2018校园招聘算法题)
  20. 转载:爬取百度图库中猫的图片

热门文章

  1. python 从windows移植到linux后,ImportError:No module named xxxx
  2. CDC框架之Debezium使用
  3. 把成都市所有图书馆标记在地图上需要几步?超简单
  4. the sentiments when install labelimage
  5. php网页采集 修正版
  6. C++11之后的decltype类型指示符
  7. RSA加密、解密、签名、验签(验证签名)RSA算法原理
  8. 洛谷P2585[ZJOI2006]三色二叉树(树形DP)
  9. Spring Boot中Configuration problem: Cannot locate BeanDefinitionParser for element 的问题分析
  10. python3结果窗口打开_python3+PyQt5 使用三种不同的简便项窗口部件显示数据的方法...