列表布局|列表布局 (1)--RecycleView 官方介绍翻译

Create a List with RecyclerView 使用RecyclerView创建列表布局

If your app needs to display a scrolling list of elements based on large data sets (or data that frequently changes), you should use RecyclerView as described on this page.

如果你的APP需要显示大量数据集合的滚动列表布局(或者数据经常变化),你应该使用RecyclerView来实现这个页面。
*Tip: Start with some template code in Android Studio by clicking File > New > Fragment > Fragment (List). Then simply add the fragment to your activity layout.

在Android studio中通过点击’文件‘->‘新建’->‘Fragment’->'Fragment(List)'.就可以简单的添加Fragment到你的activity布局中。
列表布局|列表布局 (1)--RecycleView 官方介绍翻译
文章图片
Figure 1 up-w280 Figure 1. A list using RecyclerView
列表布局|列表布局 (1)--RecycleView 官方介绍翻译
文章图片
Figure 2 up-w280 Figure 2. A list also using CardView
If you'd like to create a list with cards, as shown in figure 2, also use the CardView widget as described in Create a Card-based Layout.If you'd like to see some sample code for RecyclerView, check out the RecyclerView Sample App.

如果你想创建卡片列表,想图2一样,你也可以使用CardView控件来实现卡片布局。
如果你想查看RecyclerView的代码例子,可以点击RecyclerView Sample App
RecyclerView overview RecyclerView 概述
The RecyclerView widget is a more advanced and flexible version of ListView.In the RecyclerView model, several different components work together to display your data. The overall container for your user interface is a RecyclerView object that you add to your layout. The RecyclerView fills itself with views provided by a layout manager that you provide. You can use one of our standard layout managers (such asLinearLayoutManager or GridLayoutManager), or implement your own.

RecyclerView 控件是更高级更灵活的ListView。
在Recyclerview模块,不同的组件一起显示你的数据。你只需要在用户界面上添加RecycleView控件。RecyclerView会通过你提供的layout manger 来填充数据到视图上。可以使用(LinearLayoutManager(线性布局) 或者 GridLayoutManager(表格布局)),也可以自定义布局。
The views in the list are represented by view holder objects. These objects are instances of a class you define by extending RecyclerView.ViewHolder. Each view holder is in charge of displaying a single item with a view. For example, if your list shows music collection, each view holder might represent a single album. The RecyclerViewcreates only as many view holders as are needed to display the on-screen portion of the dynamic content, plus a few extra. As the user scrolls through the list, the RecyclerView takes the off-screen views and rebinds them to the data which is scrolling onto the screen.The view holder objects are managed by an adapter, which you create by extending RecyclerView.Adapter. The adapter creates view holders as needed. The adapter also binds the view holders to their data. It does this by assigning the view holder to a position, and calling the adapter's onBindViewHolder() method. That method uses the view holder's position to determine what the contents should be, based on its list position.

列表的view通过viewholder对象表示。这些对象是RecyclerView.ViewHolder的子类。每个view的holder负责显示每一个view。例如,如果你的列表显示音乐collection,每一个view holder 可能会表示一张专辑。Recyclerview 只会创建需要显示与屏幕内容需要的相同数量的viewHolder,加上几个额外的。当用户滑动列表时,RecyclerView将会取消绑定一些事图,并重新绑定到哪些滑动进屏幕的列表上。
viewHolder对象由RecycleView.Adapter的子类管理。adapter通过onBindViewHolder()将viewHolder绑定到position(下标)上,从而能在需要的时候创建viewHolder,并且绑定相应的数据到view上。该方法使用viewHolder的position 来确定list中的对应的数据。
This RecyclerView model does a lot of optimization work so you don't have to:?When the list is first populated, it creates and binds some view holders on either side of the list. For example, if the view is displaying list positions 0 through 9, the RecyclerView creates and binds those view holders, and might also create and bind the view holder for position 10\. That way, if the user scrolls the list, the next element is ready to display.?As the user scrolls the list, the RecyclerView creates new view holders as necessary. It also saves the view holders which have scrolled off-screen, so they can be reused. If the user switches the direction they were scrolling, the view holders which were scrolled off the screen can be brought right back. On the other hand, if the user keeps scrolling in the same direction, the view holders which have been off-screen the longest can be re-bound to new data. The view holder does not need to be created or have its view inflated; instead, the app just updates the view's contents to match the new item it was bound to.?When the displayed items change, you can notify the adapter by calling an appropriate RecyclerView.Adapter.notify…() method. The adapter's built-in code then rebinds just the affected items.

RecyclerView帮你做了很多额外的工作:
  • 当view第一次显示是,它创建需要显示的viewHolder并绑定到相应的数据上。例如,如果显示第0-9项,RecyclerView创建并绑定相应的viewHloders,也可以同时创建并绑定第10项viewHloder,如果用户滑动列表,则下一项数据已经准备好可以显示了。
  • 当用户滑动列表,RecyclerView会创建相邻的需要显示的viewHolder,同时会把那些已经划出屏幕的viewHolder保存起来,这样用户往回划就能重新使用刚才的viewHolder。同时,如果用户一直在一个方向上划,那那些最远的ViewHolder就会被拿回来重新绑定要显示的数据。ViewHolder 并不需要创建view的inflated,只需要更新view的内容去匹配到新的item上面。
  • 当显示的items发生变化时,你可以通知adapter通过调用notify()方法。adapter提供的方法来重新绑定受影响的视图。
Add the support library****(添加依赖库)
To access the RecyclerView widget, you need to add the v7 Support Libraries to your project as follows:

要使用RecyclerView控件,需要使用以下方式引入v7Support Libraries到你的项目中:
dependencies { implementation 'com.android.support:recyclerview->v7:27.1.1' }

Add RecyclerView to your layout Now you can add the RecyclerView to your layout file. For example, the following layout uses RecyclerView as the only view for the whole layout:
现在你可以添加RecyclerView到你的布局文件中。例如,下面的布局使用RecyclerView作为唯一的布局在整个layout中:

Once you have added a RecyclerView widget to your layout, obtain a handle to the object, connect it to a layout manager, and attach an adapter for the data to be displayed:

当你添加了RecyclerView控件到你的布局文件中,就可以并绑定到对象上,连接上layoutManager,然后将数据连接到adapter上去显示:
public class MyActivity extends Activity { private RecyclerView mRecyclerView; private RecyclerView.Adapter mAdapter; private RecyclerView.LayoutManager mLayoutManager; @Override protected 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 RecyclerView mRecyclerView.setHasFixedSize(true); // use a linear layout manager mLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager); // specify an adapter (see also next example) mAdapter = new MyAdapter(myDataset); mRecyclerView.setAdapter(mAdapter); } // ... }

Add a list adapter
To feed all your data to the list, you must extend the RecyclerView.Adapter class. This object creates views for items, and replaces the content of some of the views with new data items when the original item is no longer visible.The following code example shows a simple implementation for a data set that consists of an array of strings displayed using TextView widgets:

要把所有的数据添加到列表中,你需要继承RecyclerView.Adapter类,它会创建item的view,然后将新数据绑定到某些已经存在但很久没使用的view上。
下面的代码例子演示了如何将String数组显示到textview控件上:
public class MyAdapter extends RecyclerView.Adapter { 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)@Override public 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 thelayout manager)@Override public void onBindViewHolder(ViewHolder holder, int position) {// - get element from your dataset at this position // - replace the contents of the view with that element holder.mTextView.setText(mDataset[position]); }// Return the size of your dataset (invoked by the layout manager)@Override public int getItemCount() { return mDataset.length; } }

The layout manager calls the adapter's onCreateViewHolder() method. That method needs to construct a RecyclerView.ViewHolder and set the view it uses to display its contents. The type of the ViewHolder must match the type declared in the Adapter class signature. Typically, it would set the view by inflating an XML layout file. Because the view holder is not yet assigned to any particular data, the method does not actually set the view's contents.The layout manager then binds the view holder to its data. It does this by calling the adapter's onBindViewHolder()method, and passing the view holder's position in the RecyclerView. The onBindViewHolder() method needs to fetch the appropriate data, and use it to fill in the view holder's layout. For example, if the RecyclerView is displaying a list of names, the method might find the appropriate name in the list, and fill in the view holder's TextView widget.If the list needs an update, call a notification method on the RecyclerView.Adapter object, such asnotifyItemChanged(). The layout manager then rebinds any affected view holders, allowing their data to be updated.

layoutManager 调用adapter的onCreateViewHolder()方法,onCreateViewHolder()方法创建ViewHolder,并设置view去显示内容。
ViewHolder必须是Adapter类的泛型类型。一般来说,他需要通过inflating一个xml布局文件来设置view。因为viewHolder 还没分配相应的数据,这个方法实际上并不设置view的内容。
布局管理器通过调用adapter的OnBindViewHolder()方法,以及viewHolder的position来绑定viewHolder和它的数据。onBindViewHolder()方法需要选择相应的数据来写入ViewHolder布局中。例如,使用RecyclerView()方法来显示名称列表,这个方法会找到列表中相应的名称,然后写入TextView控件中。
如果列表需要更新数据,调用notification方法,例如notifyItemChanged()方法。布局管理器会重新绑定相应的数据,让数据可以更新。
Tip: You might find the ListAdapter class useful for determining which items in your list need to be updated when the list changes.

你可能会发现ListAdapter类有助于在根系数据是确认那些数据需要被更新。
Customize your RecyclerView
You can customize the RecyclerView objects to meet your specific needs. The standard classes provide all the functionality that most developers will need; in many cases, the only customization you need to do is design the view for each view holder and write the code to update those views with the appropriate data. However, if your app has specific requirements, you can modify the standard behavior in a number of ways. The following sections describe some of the other common customizations.

你可以自定义RecyclerView类来实现你的特殊需求。标准类提供来了几乎所有开发者需要使用到的方法;在很多情况下,你只需要去设计每个viewHolder的view,然后通过代码吧相应的数据更新到哪些view上。同时,如果你的app有特殊的需求,你可以修改某些方法的行为。下面的选项描述一些其他的常用定制。
Modifying the layout
The RecyclerView uses a layout manager to position the individual items on the screen and determine when to reuse item views that are no longer visible to the user. To reuse (or recycle) a view, a layout manager may ask the adapter to replace the contents of the view with a different element from the dataset. Recycling views in this manner improves performance by avoiding the creation of unnecessary views or performing expensive findViewById()lookups. The Android Support Library includes three standard layout managers, each of which offers many customization options:?LinearLayoutManager arranges the items in a one-dimensional list. Using a RecyclerView with LinearLayoutManager provides functionality like the older ListView layout.?GridLayoutManager arranges the items in a two-dimensional grid, like the squares on a checkerboard. Using a RecyclerView with GridLayoutManager provides functionality like the older GridView layout.?StaggeredGridLayoutManager arranges the items in a two-dimensional grid, with each column slightly offset from the one before, like the stars in an American flag.If none of these layout managers suits your needs, you can create your own by extending the RecyclerView.LayoutManager abstract class.

RecyclerView 使用布局管理器来为那些显示在屏幕上的item view定位,并且决定什么时候重用那些已经不显示的item view。要重用view,布局管理器可能会要求适配器使用数据集中的不同元素替代视图中的内容。以这种方式回收view可以避免创建不必要的view,或者是使用代价昂贵的findViewById()方法。Android 依赖库导入了三种标准的布局管理器,每一个都会提供很多个性化的选项:
  • LinearLayoutManager 将item整理为一个线性布局。使用LinearLayoutManager提供了类似于旧的ListView的功能。
  • GridLayoutManager 将item整理为表格布局,就像棋盘上面的方块。使用GirdLayoutManager提供了类似于旧的GirdView布局的功能。
  • StaggeredGirdLayoutManager 将item整理为表格布局,每一列都略微偏离,就像美国国旗上的星星一样。
如果没有一个布局管理器能满足你的需求,你可以创建自己的布局管理器,只要继承RecyclerView.LayoutManager 抽象类。
Add item animations Whenever an item changes, the RecyclerView uses an animator to change its appearance. This animator is an object that extends the abstract RecyclerView.ItemAnimator class. By default, the RecyclerView uses DefaultItemAnimator to provide the animation. If you want to provide custom animations, you can define your own animator object by extending RecyclerView.ItemAnimator.
当item发生变化时,RecyclerView使用动画来改变它们的位置。这个动画时抽象类RecyclerView.ItemAnimator的子类。默认的,RecyclerView使用DefaultItemAnimator来提供动画效果.如果你想提供自定义动画效果,你可以实现RecyclerView.ItemAnimator.
Enable list-item selection
The recyclerview-selection library enables users to select items in RecyclerView list using touch or mouse input. You retain control over the visual presentation of a selected item. You can also retain control over policies controlling selection behavior, such as items that can be eligible for selection, and how many items can be selected.To add selection support to a RecyclerView instance, follow these steps:1.Determine which selection key type to use, then build a ItemKeyProvider.There are three key types that you can use to identify selected items: Parcelable (and all subclasses likeUri), String, and Long. For detailed information about selection-key types, seeSelectionTracker.Builder.2.Implement ItemDetailsLookup.ItemDetailsLookup enables the selection library to access information about RecyclerView items given aMotionEvent. It is effectively a factory for ItemDetails instances that are backed up by (or extracted from) a RecyclerView.ViewHolder instance.3.Update item Views in RecyclerView to reflect that the user has selected or unselected it.The selection library does not provide a default visual decoration for the selected items. You must provide this when you implement onBindViewHolder(). The recommended approach is as follows:?In onBindViewHolder(), call setActivated() (not setSelected()) on the View object with trueor false (depending on if the item is selected).?Update the styling of the view to represent the activated status. We recommend you use a color state list resource to configure the styling.4.Use ActionMode to provide the user with tools to perform an action on the selection.Register a SelectionTracker.SelectionObserver to be notified when selection changes. When a selection is first created, start ActionMode to represent this to the user, and provide selection-specific actions. For example, you may add a delete button to the ActionMode bar, and connect the back arrow on the bar to clear the selection. When the selection becomes empty (if the user cleared the selection the last time), don't forget to terminate action mode.5.Perform any interpreted secondary actionsAt the end of the event processing pipeline, the library may determine that the user is attempting to activate an item by tapping it, or is attempting to drag and drop an item or set of selected items. React to these interpretations by registering the appropriate listener. For more information, see SelectionTracker.Builder.

RecyclerView-selection库允许用户点击并拖动RecyclerView的item。你可以控制选中选项的视觉呈现效果。你也可以对控制行为的策略进行控制,比如可选项目,或者可选项目的数量。
下面步骤可以添加Selection的支持到RecyclerView实例:
  1. 确定使用哪种selection,然后建立ItemKeyProvider。有三种关键类型你可以选择来标记选中的item:Parcelable及其子类、String类型和Long类型。更多详细的信息关于Selection-key 的类型可以查看SelectionTracker.Builder
  2. 实现ItemDetailsLookup。
ItemDetailsLookup可以得到RecyclerView items获取到的事件信息。它实际上是一个ViewHolder实例的备份。
  1. 更新item的事图来响应用户的选择或者取消选择。Selection依赖并没有提供默认的选择效果,你必须在OnBindViewHolder中提供:
  • 在onBindViewHolder()中,通过item是否被选中来调用setActivated()(不是setSelected())方法
  • 更新view的状态来显示活跃状态。建议使用 color state list资源来表示是否选中。
4.通过ActionMode来确定用户的手势操作
注册一个SelectionTracker.SelectionObserver来接收通知状态改变的通知。首次创建section时,启动ActionMode来将其展示给用户,并提供Selection-specific 操作,例如,你可以在ActionMode上添加一个删除按钮,并连接栏上的返回按钮来清楚操作。当Selection为空时,不要忘记退出操作模式
5.执行所有的
在事件处理的最后,库会监听到用户是在尝试去活跃,还是在拖动或者丢弃它。要实现这样的效果,需要注册一个相应的listener,想要了解更多的信息,可以查看 SelectionTracker.Builder.
  1. Assemble everything with SelectionTracker.Builder
The following example shows how to put these pieces together by using the Long selection key:
6.集合所有的东西到 SelectionTracker.Builder
下面的代码演示了如何使用Long selection key 将这些合到一起:
SelectionTracker tracker = new SelectionTracker.Builder<>( "my-selection-id", recyclerView, new StableIdKeyProvider(recyclerView), new MyDetailsLookup(recyclerView), StorageStrategy.createLongStorage()) .withOnItemActivatedListener(myItemActivatedListener) .build();

In order to build a SelectionTracker instance, your app must supply the same RecyclerView.Adapterthat you used to initialize RecyclerView to SelectionTracker.Builder. For this reason, you will most likely need to inject the SelectionTracker instance, once created, into your RecyclerView.Adapter after the RecyclerView.Adapter is created. Otherwise, you won't be able to check an item's selected status from the onBindViewHolder() method.

为了创建SelectionTracker实例,你的APP必须提供初始化RecyclerView的adapter给SelectionTracker.Buillder.因此,你很可能在adapter创建后将SelectionTracker实例注入到你的adapter中。否则你将无法在OnBindViewHolder()中获取目标的选中状态.
7.Include selection in the activity lifecycle events.In order to preserve selection state across the activity lifecycle events, your app must call the selection tracker's onSaveInstanceState() and onRestoreInstanceState() methods from the activity'sonSaveInstanceState() and onRestoreInstanceState() methods respectively. Your app must also supply a unique selection ID to the SelectionTracker.Builder constructor. This ID is required because an activity or a fragment may have more than one distinct, selectable list, all of which need to be persisted in their saved state.

7.在activity的生命周期中使用selection
【列表布局|列表布局 (1)--RecycleView 官方介绍翻译】为了在activity的生命周期中保留选中状态,你的app必须分别在activity的onSaveInstanceState()方法和onREstoreInstanceState()方法中调用selectiontracker的onSaveInstanceState()方法和onREstoreInstanceState()方法。同时还要提供特定的Selection ID给SelectionTracker.Builder构造器.这个id是必须的,因为activity存在很多不同的可选列表,需要通过它来保留状态。

    推荐阅读