淺談RecyclerView(完美替代ListView,GridView)

Android RecyclerView 是Android5.0推出來的,導入support-v7包便可使用。html

我的體驗來講,RecyclerView絕對是一款功能強大的控件。java

首先總結下RecyclerView的特色:android

1.支持不一樣方向,不一樣排版模式,實現多種展示數據的形式,涵蓋了ListView,GridView,瀑布流等數據表現的形式app

2.內部實現了回收機制,無需咱們考慮View的複用狀況ide

3.取消了onItemClick等點擊事件,須要本身手動去寫佈局

------------------------------------------------------------------------------------post

那麼讓咱們經過一些Demo來了解RecyclerView的基本使用gradle

 android studio ui

build.gradle文件中 dependencies中添加 this

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(網格佈局)

相關文章
相關標籤/搜索