浅谈RecyclerView(完美替代ListView,GridView)

简介: Android RecyclerView 是Android5.0推出来的,导入support-v7包即可使用。 个人体验来说,RecyclerView绝对是一款功能强大的控件。 首先总结下RecyclerView的特点: 1.

Android RecyclerView 是Android5.0推出来的,导入support-v7包即可使用。

个人体验来说,RecyclerView绝对是一款功能强大的控件。

首先总结下RecyclerView的特点:

1.支持不同方向,不同排版模式,实现多种展现数据的形式,涵盖了ListView,GridView,瀑布流等数据表现的形式

2.内部实现了回收机制,无需我们考虑View的复用情况

3.取消了onItemClick等点击事件,需要自己手动去写

------------------------------------------------------------------------------------

那么让我们通过一些Demo来了解RecyclerView的基本使用

 android studio 

build.gradle文件中 dependencies中添加 

compile 'com.android.support:recyclerview-v7:22.+'

 

首先,要导入support-v7 包

import android.support.v7.widget.RecyclerView;

RecyclerView和ListView的使用一样,都需要有对应的Adapter,列表项布局,数据源

1.先写主Activity布局

可以看到RecyclerView的标签

<android.support.v7.widget.RecyclerView>

 

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2               xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto"
 3               android:layout_width="match_parent"
 4               android:layout_height="match_parent"
 5               android:orientation="vertical"
 6               tools:context="com.xqx.superapp.app.Android5Activity">
 7 
 8     <Button
 9             android:text="添加一个数据"
10             android:layout_width="wrap_content"
11             android:layout_height="wrap_content"
12             android:onClick="btnAddItem"
13             />
14     <Button
15             android:text="删除第一个"
16             android:onClick="btnRemoveItem"
17             android:layout_width="wrap_content"
18             android:layout_height="wrap_content"/>
19     
20     <android.support.v7.widget.RecyclerView
21         android:id="@+id/recycle_view"
22         android:layout_width="match_parent"
23         android:layout_height="match_parent"
24         >
25     </android.support.v7.widget.RecyclerView>
26 
27 </LinearLayout>

 

菜单项布局,标准的上面图片,下面文字

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:gravity="center"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
        <ImageView
                android:id="@+id/item_icon"
                android:src="@mipmap/machao_moqi"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
        <TextView
                android:id="@+id/item_title"
                android:text="名称"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                />
</LinearLayout>

 

2.接下来就看Activity代码了

首先看成员变量,与ListView,GridView一样 标准三样, 控件,数据源,适配器

private List<String> data;          
private RecyclerView recyclerView;
private MyRecycleAdapter adapter;   //自定义适配器,继承RecyclerView.Adapter

 

接着我们必须要自定义一个ViewHolder,这个ViewHolder 必须要继承 RecyclerView.ViewHolder

注意RecyclerView不再提供onItemClick事件监听,所以需要我们自己手工写监听事件的方法

private static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public ImageView imageView;
        public TextView textView;

        public ViewHolder(View itemView) {
            super(itemView);
            // 通常ViewHolder的构造,就是用于获取控件视图的
            imageView = (ImageView) itemView.findViewById(R.id.item_icon);
            textView = (TextView) itemView.findViewById(R.id.item_title);
            // TODO 后续处理点击事件的操作
            itemView.setOnClickListener(this);

        }
        @Override
        public void onClick(View v) {
            int position = getAdapterPosition();
            Context context = imageView.getContext();
            Toast.makeText(context,"显示第"+position+"个项",Toast.LENGTH_SHORT).show();
        }
    }

 

再让我们看自定义适配器,注意这里的参数是ViewHolder,这个ViewHodler是我们自己的,不要导入v7包下的ViewHolder,

之后要重写三个方法

private class MyRecycleAdapter extends RecyclerView.Adapter<ViewHolder>{
  
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
return null;
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {

}

@Override
public int getItemCount() {
return 0;
}

}

在自定义适配器MyRecycleAdapter中,首先要写一个构造方法,因为有数据源,所有构造方法里必然有List

private List<String> strings;
public MyRecycleAdapter(List<String> strings) {
     this.strings = strings;
}

然后就要重写三个方法了,

 1 @Override
 2 public int getItemCount() {
 3     int ret = 0;
 4     if (strings != null) {
 5         ret = strings.size();
 6      }
 7         return ret;
 8 }
 9 
10  @Override
11         public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
12             ViewHolder ret = null;
13             // 不需要检查是否复用,因为只要进入此方法,必然没有复用
14             // 因为RecyclerView 通过Holder检查复用
15             View v = LayoutInflater.from(Android5Activity.this).inflate(R.layout.item_recycler, viewGroup, false);
16             ret = new ViewHolder(v);
17             return ret;
18         }
19 
20 @Override
21         public void onBindViewHolder(ViewHolder viewHolder, int i) {
22             // 1.这里进行图片的加载
23             viewHolder.textView.setText(strings.get(i));
24             int resId = R.mipmap.ic_launcher;
25             int index = i%5;
26             switch (index){
27                 case 0:
28                     resId = R.mipmap.a11;
29                     break;
30                 case 1:
31                     resId = R.mipmap.a33;
32                     break;
33                 case 2:
34                     resId = R.mipmap.a22;
35                     break;
36             }
37             viewHolder.imageView.setImageResource(resId);
38         }
View Code

 

---------------------------------------------------------------------------------------------------------------

完成自定义适配器和自定义ViewHolder的代码 就要进行RecyclerView的使用了

首先 要了解  RecyclerView.LayoutManager 这个属性

用于进行一个布局的设置,可以设置显示模式,ListView或者GridView或者瀑布流

1.ListView显示模式

1 // 1.线性布局
2         LinearLayoutManager layoutManager =
3                 new LinearLayoutManager(this,   // 上下文
4                                         LinearLayout.VERTICAL,  //垂直布局,
5                                         false);

                                    

2.GridView显示模式

1 // 2.Grid布局
2         RecyclerView.LayoutManager layoutManager =
3                 new GridLayoutManager(this,
4                                       2,  // 每行显示item项数目
5                                       GridLayoutManager.HORIZONTAL, //水平排列
6                                       false
7                                       );

                                    

3.瀑布流显示模式

1 // 3.瀑布流
2         RecyclerView.LayoutManager layoutManager =
3                 new StaggeredGridLayoutManager(3,  // 每行显示的item项数目
4                         StaggeredGridLayoutManager.VERTICAL);  // 垂直排列

 

以上三种显示模式任意设置一种 就可以继续下面的代码

recyclerView.setLayoutManager(layoutManager);
        // 设置 RecyclerView的Adapter
        // 注意一定在设置了布局管理器之后调用
        adapter = new MyRecycleAdapter(data);
        recyclerView.setAdapter(adapter);

 

最后记得加上“添加一个数据”,“删除第一个数据”的按钮响应事件。

首先看一下以往我们对listview,gridview等等的删除某一项的操作

先在数据源中删除该位置的数据,然后刷新整个适配器,那么就可能会造成列表闪屏的问题,还有为了删除添加一个数据项而操作整个数据源的问题

public void btnAddItem(View view) {
        data.add(0,"Time:"+System.currentTimeMillis());
        adapter.notifyDataSetChanged();
    }
    public void btnRemoveItem(View view) {
        if (!data.isEmpty()) {
            data.remove(0);
        }
        adapter.notifyItemRemoved(0);
    }

 而RecyclerView为我们提供了一些新的实用的方法:

public void add(ViewModel item, int position) {
    items.add(position, item);    //数据源先添加该数据
    notifyItemInserted(position); //在某个位置刷新即可
}
 
public void remove(ViewModel item) {
    int position = items.indexOf(item);
    items.remove(position);      //数据源先删除该数据
    notifyItemRemoved(position); //在某个位置删除即可
}

 

完整代码:

  1 package com.xqx.superapp.app;
  2 
  3 import android.app.Activity;
  4 import android.content.Context;
  5 import android.support.v7.app.ActionBarActivity;
  6 import android.os.Bundle;
  7 import android.support.v7.widget.GridLayoutManager;
  8 import android.support.v7.widget.LinearLayoutManager;
  9 import android.support.v7.widget.RecyclerView;
 10 import android.support.v7.widget.StaggeredGridLayoutManager;
 11 import android.util.Log;
 12 import android.view.*;
 13 import android.widget.*;
 14 
 15 import java.util.LinkedList;
 16 import java.util.List;
 17 
 18 
 19 public class Android5Activity extends Activity {
 20 
 21     private List<String> data;
 22     private RecyclerView recyclerView;
 23     private MyRecycleAdapter adapter;
 24 
 25     @Override
 26     protected void onCreate(Bundle savedInstanceState) {
 27         super.onCreate(savedInstanceState);
 28         setContentView(R.layout.activity_android5);
 29         data = new LinkedList<String>();
 30         recyclerView = (RecyclerView) findViewById(R.id.recycle_view);
 31         // 设置布局管理器
 32         // 支持 单列线性排列,支持GridView模式,瀑布流模式
 33         // 1.线性布局
 34         LinearLayoutManager layoutManager =
 35                 new LinearLayoutManager(this,   // 上下文
 36                                         LinearLayout.VERTICAL,  //垂直布局,
 37                                         false);
 38 
 39 //        // 2.Grid布局
 40 //        RecyclerView.LayoutManager layoutManager =
 41 //                new GridLayoutManager(this,
 42 //                                      2,
 43 //                                      GridLayoutManager.HORIZONTAL,
 44 //                                      false
 45 //                                      );
 46 //
 47 //         // 3.瀑布流
 48 //        RecyclerView.LayoutManager layoutManager =
 49 //                new StaggeredGridLayoutManager(3,
 50 //                        StaggeredGridLayoutManager.VERTICAL);
 51         recyclerView.setLayoutManager(layoutManager);
 52         // 设置 RecyclerView的Adapter
 53         // 注意一定在设置了布局管理器之后调用
 54         adapter = new MyRecycleAdapter(data);
 55         recyclerView.setAdapter(adapter);
 56     }
 57 
 58     public void btnAddItem(View view) {
 59         data.add(0,"Time:"+System.currentTimeMillis());
 60         adapter.notifyDataSetChanged();
 61     }
 62 
 63     public void btnRemoveItem(View view) {
 64         if (!data.isEmpty()) {
 65             data.remove(0);
 66         }
 67         adapter.notifyItemRemoved(0);
 68     }
 69 
 70     /**
 71      * 继承RecyclerView.Adapter,用于显示数据
 72      * 需要定义并且使用 ViewHolder ,必须要使用
 73      */
 74     private class MyRecycleAdapter extends RecyclerView.Adapter<ViewHolder>{
 75         private List<String> strings;
 76         public MyRecycleAdapter(List<String> strings) {
 77             this.strings = strings;
 78         }
 79 
 80         @Override
 81         public int getItemCount() {
 82             int ret = 0;
 83             if (strings != null) {
 84                 ret = strings.size();
 85             }
 86             return ret;
 87         }
 88 
 89         @Override
 90         public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
 91             ViewHolder ret = null;
 92             // 不需要检查是否复用,因为只要进入此方法,必然没有复用
 93             // 因为RecyclerView 通过Holder检查复用
 94             View v = LayoutInflater.from(Android5Activity.this).inflate(R.layout.item_recycler, viewGroup, false);
 95             ret = new ViewHolder(v);
 96             return ret;
 97         }
 98 
 99         @Override
100         public void onBindViewHolder(ViewHolder viewHolder, int i) {
101             viewHolder.textView.setText(strings.get(i));
102             int resId = R.mipmap.ic_launcher;
103             int index = i%5;
104             switch (index){
105                 case 0:
106                     resId = R.mipmap.a11;
107                     break;
108                 case 1:
109                     resId = R.mipmap.a33;
110                     break;
111                 case 2:
112                     resId = R.mipmap.a22;
113                     break;
114             }
115             viewHolder.imageView.setImageResource(resId);
116         }
117     }
118 
119     /**
120      * 创建自己的ViewHolder ,必须要继承RecyclerView.ViewHolder
121      */
122     private static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
123         public ImageView imageView;
124         public TextView textView;
125 
126         public ViewHolder(View itemView) {
127             super(itemView);
128             // 通常ViewHolder的构造,就是用于获取控件视图的
129             imageView = (ImageView) itemView.findViewById(R.id.item_icon);
130             textView = (TextView) itemView.findViewById(R.id.item_title);
131             // TODO 后续处理点击事件的操作
132             itemView.setOnClickListener(this);
133 
134         }
135         @Override
136         public void onClick(View v) {
137             int position = getAdapterPosition();
138             Context context = imageView.getContext();
139             Toast.makeText(context,"显示第"+position+"个项",Toast.LENGTH_SHORT).show();
140         }
141     }
142 }
View Code

 

 

-------------------------------------------------------------------------------------------------------------

其他相关:

浅谈FloatingActionButton(悬浮按钮)

浅谈DrawerLayout(抽屉效果)

浅谈TabLayout(ViewPager+Tab联动)

浅谈GridLayout(网格布局)

相关文章
|
Java API Android开发
ListView简单实用
自定义BaseAdapter,绑定ListView的最简单例子
156 0
C#-ListView的使用
ListView顾名思义用来做列表数据展示,也是我们在开发中经常使用的控件之一,接下来将展示下它的一些使用场景,以满足不同的需求。
160 0
|
C#
C#-ListView
C# ListView
112 0
Flutte 之 ListView
Flutte 之 ListView
99 0
Flutte 之 ListView
|
XML Android开发 数据格式
ListView
在这里给大家分享Android的ListView控件的一些经验,能力有限,还望大家多多指教,不喜勿喷哦,kensoon918@163.com only for feedback
1549 0
|
Android开发 数据格式 XML
ListView的使用
ListView样式设置 取消Item点击变色效果 android:listSelector=”@android:color/transparent” Item条目高度的设定 ...
807 0
Listview 多个ViewHolder实现
简单代码示例:   package com.edaixi.adapter; import android.content.Context; import android.view.View; import android.
977 0
|
移动开发 数据库 Android开发
Android控件开发——ListView
上篇博客解决了Android客户端通过WebService与服务器端程序进行交互的问题,这篇博客重点关注两个问题,一个是Android应用程序如何与本机文件型数据库SQLite进行交互,另一问题则是如何在ListView中按照我们想要的界面效果进行展示。
855 0
解决ListView嵌套ListView遇到的问题
Listview嵌套会造成的问题主要是子listview的高度错误导致内容不能正常显示完,解决这个问题,我个人第一个想法就是重新计算子listview的高度,代码如下: private void setListViewHeightBasedOnChildren(ListView listView) { if(listView == null) return; Li
1223 0