Android RecyclerView初探

RecyclerView和CardView是Android L兼容包(support libarary)中最新增加的两个widget。而且二者都符合Android material design风格。 基本的信息请看官方文档和例子.

RecyclerView

引用Android官方语:这是一种更加高级、灵活的ListView。那么相对于ListView,它究竟强在哪了呢?我们又该如何使用?

特点

  • 不仅仅可以替代ListView,还可以用作GridView,甚至瀑布流都可以。
  • 提供了默认的添加或者删除ListView中某一项时的动画。当然你也可以实现自定义的动画。
  • 提供了layoutmanager来专门管理显示。从而更好的将显示与数据分离开。事实上,这一特性决定了特性1,也就是可以实现不同的view形式。
  • 在Adapter中强制使用ViewHolder pattern

相关类

接下来看看RecyclerView相关的类以及其用途:

Class Purpose Optional
Adapter 提供数据,并且为每一个条目创建views Required
ViewHolder 缓存每一个entry的views的references Required
LayoutManager 用来定义所有的的entry的布局 Required, but default implementations available
ItemDecoration 用来定义显示每一个条目周边的装饰. Default behaviour, but can be overridden
ItemAnimator 用来定义增加或者删除一项时的动画 Default behaviour, but can be overridden

相关的开源库

目前在Github上已经有不少的RecyclerView相关的开源项目,有需要的时候可以参考或者拿来直接用:

CardView

CardView比较简单直接,本质上就是一个FrameLayout, 在开发时只需要将需要在每个CardView中显示的内容填充进去即可。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
... >
    <!-- A CardView that contains a TextView -->
    <android.support.v7.widget.CardView
        xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:id="@+id/card_view"
        android:layout_gravity="center"
        android:layout_width="200dp"
        android:layout_height="200dp"
        card_view:cardCornerRadius="4dp">

        //Add your cardview content here

    </android.support.v7.widget.CardView>
</LinearLayout>

实际使用中发现最终的效果很不错,推荐使用!

一个例子

接下来我会提供一个使用RecyclerVIew以及CardView的例子来展示它们如何使用。

  • 加入依赖

在使用之前,先在build.gradle中加入依赖:

dependencies {
    ...
    compile 'com.android.support:cardview-v7:21.0.+'
    compile 'com.android.support:recyclerview-v7:21.0.+'
}
  • 定义主layout xml,里面用上RecyclerView
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>
  • 定义RecyclerView的item layout,我们采用CardView来展示每一条记录:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp">

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/cv">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="16dp">

                <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/photo"
                android:layout_alignParentLeft="true"
                android:layout_alignParentTop="true"
                android:src="@mipmap/ic_launcher"
                android:layout_marginRight="16dp" />

               <TextView
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:id="@+id/tweet_id"
               android:layout_toRightOf="@+id/photo"
               android:layout_alignParentTop="true"
               android:textSize="30sp"
               tools:text="ID 12" />

               <TextView
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:id="@+id/tweet_content"
               android:layout_toRightOf="@+id/photo"
               android:layout_below="@+id/tweet_id"
               tools:text="I am the content of tweet"/>

        </RelativeLayout>

    </android.support.v7.widget.CardView>

</LinearLayout>
  • 实现RecyclerView的adpter

    package com.zhixin.twittersample.model.adapter;
    
    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    import com.zhixin.twittersample.R;
    import com.zhixin.twittersample.model.twitter.Tweet;
    
    import java.util.ArrayList;
    
    /**
     * Created by Zhixin on 4/21/2015.
    */
    public class TwitterAdapter extends RecyclerView.Adapter<TwitterAdapter.ViewHolder> {
        private ArrayList<Tweet> mDataSet;
    
        public class ViewHolder extends RecyclerView.ViewHolder {
            public TextView txtHeader;
            public TextView txtFooter;
    
            public ViewHolder(View itemView) {
                super(itemView);
                txtHeader = (TextView)itemView.findViewById(R.id.tweet_id);
                txtFooter = (TextView)itemView.findViewById(R.id.tweet_content);
            }
        }
    
        // Provide a suitable constructor (depends on the kind of dataset)
        public TwitterAdapter(ArrayList<Tweet> myDataset) {
           mDataSet = myDataset;
        }
    
        // Create new views (invoked by the layout manager)
        @Override
        public TwitterAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.tweet_item/*tweet_entry*/, 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 viewHolder, int i) {
            String tweetContent = mDataSet.get(i).getText();
            String displayName = mDataSet.get(i).getUser().getName();
            viewHolder.txtFooter.setText(tweetContent);
            viewHolder.txtHeader.setText(displayName);
        }
    
        @Override
        public int getItemCount() {
            return mDataSet.size();
        }
    }
    
  • 在main activity中提取RecyclerView并给它set adapter

    mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
    mAdapter = new TwitterAdapter(tweet);
    mRecyclerView.setAdapter(mAdapter);
    

最终的运行效果如下:

总结

好了,基本的RecyclerView以及CardView的介绍以及使用就是这样了,你可以点击这里下载示例代码,该代码是从Tweeter上取指定用户的发布的所有tweet,然后在RecyclerView中展示出来,其中每一条记录是一个CardView。