Android RecyclerView 的基本使用

我们做Android开发,当需要大量加载图片时,一般会用到ListView、GridView等,那么RecyclerView这样的控件又能做什么用呢,为什么要用RecyclerView呢?
RecyclerView is a more advanced and flexible version of ListView. This widget is a Container for large sets of views that can be recycled and scrolled very efficiently. Use the RecyclerView widget when you have lists with elements that change dynamically.
简单说,它是ListView的进化,为了当你需要动态展示一组数据的时候就会需要它。

RecyclerView的整体使用思路如下:

  • 你想要控制其显示的方式,请通过布局管理器LayoutManager

  • 你想要控制Item间的间隔(可绘制),请通过ItemDecoration

  • 你想要控制Item增删的动画,请通过ItemAnimator
    通过以上三步设置,可以让RecyclerView显示出各种神奇的效果出来。

    RecyclerView使用过程如下:
1.RecyclerView是support-v7包中的新组件,使用之前需要导入support-v7。
![](http://upload-images.jianshu.io/upload_images/3897939-29f8b6abf7ba2310?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2.activity_main.xml的布局如下,在布局文件里引用RecyclerView控件
<span style="font-family:SimHei;font-size:14px;"><?xml version="1.0" encoding="utf-8"?>  
<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"  
    tools:context="com.example.ahuang.recyclerview.MainActivity">  
  
    <android.support.v7.widget.RecyclerView  
        android:id="@+id/recyclerView"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent">  
    </android.support.v7.widget.RecyclerView>  
</RelativeLayout>  
</span>  ```
###### 3.每个Item的布局如下,很简单,只有一个TextView

<span style="font-family:SimHei;font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
</span> ```

4. RecyclerView的适配器
  • RecyclerView的适配器继承自RecyclerView.Adapter
  • 重写内部类RecyclerView.ViewHolder
  • 实现onCreateViewHolder(),onBindViewHolder()和getItemCount()三个方法。
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{  
   Context context;  
   List<String> list;  
 
   public MyAdapter(Context context,List<String> list){  
       this.context=context;  
       this.list=list;  
   }  
   @Override  
   public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  
       MyViewHolder holder=new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.lv_item_layout,parent,false));  
 
       return holder;  
   }  
 
   @Override  
   public void onBindViewHolder(MyAdapter.MyViewHolder holder, int position) {  
       holder.tv.setText(list.get(position));  
   }  
 
   @Override  
   public int getItemCount() {  
       return list.size();  
   }  
 
   public class MyViewHolder extends RecyclerView.ViewHolder{  
 
       TextView tv;  
 
       public MyViewHolder(View itemView) {  
           super(itemView);  
           tv=(TextView) itemView.findViewById(R.id.textView);  
       }  
   }  
}  
</span>   ```
###### 5.主Activity中实现
只需上文提到的关键三步即可实现。

public class MainActivity extends ActionBarActivity {

private RecyclerView mRecyclerView;  
private List<String> list;  
private MyAdapter myAdapter;  

@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.activity_main);  

    init();  
    mRecyclerView=(RecyclerView) findViewById(R.id.recyclerView);  
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));  
    mRecyclerView.setAdapter(new MyAdapter(this,list));  

}  

private void init(){  
    list=new ArrayList<String>();  
    for(int i='A';i<'z';i++){  
        list.add(""+(char)i);  
    }  
}  

} ```
效果如下



但是,可以看到RecyclerView是没有分隔线的,而且RecyclerView并没有支持divider这样的属性,那应该怎样添加分割线呢,下面就用到了ItemDecoration,我们可以通过该方法添加分割线mRecyclerView.addItemDecoration(),通过它,我们可以随意地添加我们自定义的分割线。

当我们调用mRecyclerView.addItemDecoration()方法添加decoration的时候,RecyclerView在绘制的时候,去会绘制decorator,即调用该类的onDraw和onDrawOver方法,该类参考自:[DividerItemDecoration(http://blog.csdn.net/lmj623565791/article/details/38173061),代码如下

  • onDraw方法先于drawChildren
  • onDrawOver在drawChildren之后,一般我们选择复写其中一个即可。
  • getItemOffsets 可以通过outRect.set()为每个Item设置一定的偏移量,主要用于绘制Decorator。
/** 
 * Created by ahuang on 2016/1/8. 
 */  
public  class DividerItemDecoration extends RecyclerView.ItemDecoration{  
    private static final int[] ATTRS = new int[]{  
            android.R.attr.listDivider  
    };  
  
    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;  
  
    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;  
  
    private Drawable mDivider;  
  
    private int mOrientation;  
  
    public DividerItemDecoration(Context context, int orientation) {  
        final TypedArray a = context.obtainStyledAttributes(ATTRS);  
        mDivider = a.getDrawable(0);  
        a.recycle();  
        setOrientation(orientation);  
    }  
  
    public void setOrientation(int orientation) {  
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {  
            throw new IllegalArgumentException("invalid orientation");  
        }  
        mOrientation = orientation;  
    }  
  
    @Override  
    public void onDraw(Canvas c, RecyclerView parent) {  
        super.onDraw(c, parent);  
        if (mOrientation == VERTICAL_LIST) {  
            drawVertical(c, parent);  
        } else {  
            drawHorizontal(c, parent);  
        }  
    }  
    public void drawVertical(Canvas c, RecyclerView parent) {  
        final int left = parent.getPaddingLeft();  
        final int right = parent.getWidth() - parent.getPaddingRight();  
  
        final int childCount = parent.getChildCount();  
        for (int i = 0; i < childCount; i++) {  
            final View child = parent.getChildAt(i);  
            android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());  
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child  
                    .getLayoutParams();  
            final int top = child.getBottom() + params.bottomMargin;  
            final int bottom = top + mDivider.getIntrinsicHeight();  
            mDivider.setBounds(left, top, right, bottom);  
            mDivider.draw(c);  
        }  
    }  
  
    public void drawHorizontal(Canvas c, RecyclerView parent) {  
        final int top = parent.getPaddingTop();  
        final int bottom = parent.getHeight() - parent.getPaddingBottom();  
  
        final int childCount = parent.getChildCount();  
        for (int i = 0; i < childCount; i++) {  
            final View child = parent.getChildAt(i);  
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child  
                    .getLayoutParams();  
            final int left = child.getRight() + params.rightMargin;  
            final int right = left + mDivider.getIntrinsicHeight();  
            mDivider.setBounds(left, top, right, bottom);  
            mDivider.draw(c);  
        }  
    }  
  
    @Override  
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {  
        super.getItemOffsets(outRect, itemPosition, parent);  
        if (mOrientation == VERTICAL_LIST) {  
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());  
        } else {  
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);  
        }  
    }  
}  ```
前面说了,我们可以随意添加我们自定义的分割线,具体步骤如下:首先要自定义分割线,在drawable下画一个分割线的shape.
![](http://upload-images.jianshu.io/upload_images/3897939-7fc0c56b26b7fe67?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
在这个shape里,你可以自定义分割线的形状。

<pre name="code" class="java"><?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFC125"></solid>
<size android:height="2dp"></size>
</shape> ```
接下来就是要将自定义的shape应用到RecyclerView中。

<pre name="code" class="java"><resources>  
    <!-- Base application theme. -->  
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">  
        <!-- Customize your theme here. -->  
        <item name="android:listDivider">@drawable/divider_bg</item>  
    </style>  
  
</resources>  ```
![](http://upload-images.jianshu.io/upload_images/3897939-a0f3a45271fed70c?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)效果图如此下:
            ![](http://upload-images.jianshu.io/upload_images/3897939-24cc71f47f7cbc9b?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,050评论 25 707
  • 写RecyclerView的博客很多 建议:博客专家写 RecyclerView:主要是在有限空间,展现大量数据,...
    沈凤德阅读 865评论 0 4
  • 生活本来就不容易,而我们的不努力只会让生活变得更加无赖 前几天依据《Android群英传》的学习写了一篇笔记是关于...
    AmatorLee阅读 3,717评论 7 23
  • Tangram是阿里出品、用于快速实现组合布局的框架模型,在手机天猫Android&iOS版 内广泛使用 该框架提...
    wintersweett阅读 3,233评论 0 1
  • 原文 不尚賢,使民不爭。不貴難得之貨,使民不為盜。不見可欲,使民不亂。 是以聖人之治也,虛其心,實其腹,弱其志,強...
    老貓說話阅读 198评论 0 0