列表布局 (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布局中。

Figure 1 up-w280

Figure 1. A list using RecyclerView

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中:

<?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"/>


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<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 holder

    public static class ViewHolder extends RecyclerView.ViewHolder {

    // each data item is just a string in this case

    public 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 view

        TextView 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)

    @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 actions

At 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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,914评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,935评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,531评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,309评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,381评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,730评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,882评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,643评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,095评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,448评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,566评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,253评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,829评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,715评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,945评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,248评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,440评论 2 348

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,730评论 25 707
  • 【Android 控件 RecyclerView】 概述 RecyclerView是什么 从Android 5.0...
    Rtia阅读 307,405评论 27 439
  • 原文链接:https://github.com/opendigg/awesome-github-android-u...
    IM魂影阅读 32,904评论 6 472
  • 百花还没有开到荼蘼 有人就开始一瓣瓣地恋旧 这一路的心事总是太多 心灵不想栖息就会尽情忙碌 任凭远方日日夜夜的呼唤...
    安晓暖阅读 270评论 1 1
  • 普洱茶有“236789”,这是什么东西? 其实“236789”讲得是普洱茶的前世今生! 2 种茶(生茶和熟茶) 普...
    二摆阅读 240评论 0 0