RecyclerView的使用


什么是RecyclerView
        RecyclerView是Android 5.0 materials design中的組件之一,相應的還有CardView、Palette等。看名字我們就能看出一點端倪,沒錯,它主要的特點就是復用。我們知道,Listview中的Adapter中可以實現ViewHolder的復用。RecyclerView提供了一個耦合度更低的方式來復用ViewHolder,並且可以輕松的實現ListView、GridView以及瀑布流的效果。
 
RecyclerView的用法
        首先我們要gradle的依賴庫中添加  compile 'com.android.support:recyclerview-v7:21.+'  。如果是eclipse直接導入android-support-v7-recyclerview.jar就可以了。
 1 /**
 2 * 設置Adapter
 3 */
 4 mRecyclerView.setAdapter(mListAdapter);
 5 /**
 6 * 設置布局管理器
 7 */
 8 mRecyclerView.setLayoutManager(linearLayoutManager);
 9 /**
10 * 設置item分割線
11 */
12 mRecyclerView.addItemDecoration(itemDecoration);
13 /**
14 * 設置item動畫
15 */
16 mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        使用RecyclerView,基本上要上面四步。相比ListView只需設置Adapter而言,RecyclerView的使用看起來似乎要復雜一些。但是它的可定制性更高了,你可以自己定制自己的分割線樣式或者是item的的動畫。
        下面我們看下如何使用RecyclerView簡單實現ListView的效果。
activity:
  1 package com.bbk.lling.recyclerview;
  2 
  3 import android.support.v7.app.ActionBarActivity;
  4 import android.os.Bundle;
  5 import android.support.v7.widget.DefaultItemAnimator;
  6 import android.support.v7.widget.LinearLayoutManager;
  7 import android.support.v7.widget.RecyclerView;
  8 import android.view.Menu;
  9 import android.view.MenuItem;
 10 import android.view.View;
 11 import android.widget.Toast;
 12 
 13 import java.util.ArrayList;
 14 import java.util.List;
 15 
 16 /**
 17  * @Class: ListLayoutActivity
 18  * @Description: RecycleView實現listview的功能
 19  * @author: lling(www.liuling123.com)
 20  * @Date: 2015/10/29
 21  */
 22 public class ListLayoutActivity extends ActionBarActivity {
 23 
 24     private RecyclerView mRecyclerView;
 25     private ListAdapter mListAdapter;
 26     private List<String> mDatas;
 27 
 28     @Override
 29     protected void onCreate(Bundle savedInstanceState) {
 30         super.onCreate(savedInstanceState);
 31         setContentView(R.layout.activity_list_layout);
 32         initData();
 33         mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
 34         mListAdapter = new ListAdapter(this, mDatas);
 35         mListAdapter.setOnItemClickListener(new ListAdapter.OnItemClickListener() {
 36             @Override
 37             public void onItemClick(View view, int position) {
 38                 Toast.makeText(ListLayoutActivity.this, "Click" + mDatas.get(position), Toast.LENGTH_SHORT).show();
 39             }
 40 
 41             @Override
 42             public void onItemLongClick(View view, int position) {
 43                 mListAdapter.remove(position); //remove the item
 44                 Toast.makeText(ListLayoutActivity.this, "LongClick" + mDatas.get(position), Toast.LENGTH_SHORT).show();
 45             }
 46         });
 47         mRecyclerView.setAdapter(mListAdapter);
 48         /**
 49          * 設置布局管理器,listview風格則設置為LinearLayoutManager
 50          * gridview風格則設置為GridLayoutManager
 51          * pu瀑布流風格的設置為StaggeredGridLayoutManager
 52          */
 53         mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
 54         // 設置item分
 55         mRecyclerView.addItemDecoration(new ListItemDecoration(this, LinearLayoutManager.VERTICAL));
 56         // 設置item動畫
 57         mRecyclerView.setItemAnimator(new DefaultItemAnimator());
 58 
 59     }
 60 
 61     @Override
 62     public boolean onCreateOptionsMenu(Menu menu) {
 63         getMenuInflater().inflate(R.menu.menu_list_layout, menu);
 64         return true;
 65     }
 66 
 67     @Override
 68     public boolean onOptionsItemSelected(MenuItem item) {
 69         switch (item.getItemId()) {
 70             case R.id.add_first:
 71                 mListAdapter.add(0, "add first");
 72                 break;
 73             case R.id.add_last:
 74                 mListAdapter.add(mListAdapter.getItemCount(), "add last");
 75                 break;
 76             case R.id.remove_first:
 77                 String value = mListAdapter.remove(0);
 78                 Toast.makeText(ListLayoutActivity.this, "remove:" + value, Toast.LENGTH_SHORT).show();
 79                 break;
 80             case R.id.remove_last:
 81                 String value1 =  mListAdapter.remove(mListAdapter.getItemCount()-1);
 82                 Toast.makeText(ListLayoutActivity.this, "remove:" + value1, Toast.LENGTH_SHORT).show();
 83                 break;
 84             case R.id.horizontal:
 85                 mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
 86                 mRecyclerView.addItemDecoration(new ListItemDecoration(this, LinearLayoutManager.HORIZONTAL));
 87                 break;
 88             case R.id.vertical:
 89                 mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
 90                 mRecyclerView.addItemDecoration(new ListItemDecoration(this, LinearLayoutManager.VERTICAL));
 91                 break;
 92         }
 93         return super.onOptionsItemSelected(item);
 94     }
 95 
 96      /* ==========This Part is not necessary========= */
 97 
 98     /**
 99      * Create datas
100      */
101     protected void initData() {
102         mDatas = new ArrayList<String>();
103         for (int i = 0; i < 100; i++) {
104             mDatas.add(String.valueOf(i));
105         }
106     }
107 
108     /* ==========This Part is not necessary========= */
109 }
 
activity布局:
 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent" >
 5 
 6     <android.support.v7.widget.RecyclerView
 7         android:id="@+id/recyclerview"
 8         android:layout_width="match_parent"
 9         android:layout_height="match_parent" />
10 
11 </RelativeLayout>

 

Adapter:
  1 package com.bbk.lling.recyclerview;
  2 
  3 import android.annotation.SuppressLint;
  4 import android.content.Context;
  5 import android.support.v7.widget.RecyclerView;
  6 import android.util.Log;
  7 import android.view.LayoutInflater;
  8 import android.view.View;
  9 import android.view.ViewGroup;
 10 import android.widget.TextView;
 11 
 12 import java.util.List;
 13 
 14 /**
 15  * @Class: ListAdapter
 16  * @Description: 數據適配器
 17  * @author: lling(www.liuling123.com)
 18  * @Date: 2015/10/29
 19  */
 20 public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ItemViewHolder> {
 21 
 22     private List<String> mDatas;
 23     private LayoutInflater mInflater;
 24     private OnItemClickListener mOnItemClickListener;
 25 
 26     public ListAdapter(Context context, List<String> mDatas) {
 27         this.mDatas = mDatas;
 28         mInflater = LayoutInflater.from(context);
 29     }
 30 
 31     @Override
 32     public int getItemCount() {
 33         return mDatas.size();
 34     }
 35 
 36     @SuppressLint("NewApi")
 37     @Override
 38     public void onBindViewHolder(final ItemViewHolder itemViewHolder, final int i) {
 39         itemViewHolder.mTextView.setText(mDatas.get(i));
 40         if(mOnItemClickListener != null) {
 41             /**
 42              * 這里加了判斷,itemViewHolder.itemView.hasOnClickListeners()
 43              * 目的是減少對象的創建,如果已經為view設置了click監聽事件,就不用重復設置了
 44              * 不然每次調用onBindViewHolder方法,都會創建兩個監聽事件對象,增加了內存的開銷
 45              */
 46             if(!itemViewHolder.itemView.hasOnClickListeners()) {
 47                 Log.e("ListAdapter", "setOnClickListener");
 48                 itemViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
 49                     @Override
 50                     public void onClick(View v) {
 51                         int pos = itemViewHolder.getPosition();
 52                         mOnItemClickListener.onItemClick(v, pos);
 53                     }
 54                 });
 55                 itemViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
 56                     @Override
 57                     public boolean onLongClick(View v) {
 58                         int pos = itemViewHolder.getPosition();
 59                         mOnItemClickListener.onItemLongClick(v, pos);
 60                         return true;
 61                     }
 62                 });
 63             }
 64         }
 65     }
 66 
 67     @Override
 68     public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
 69         /**
 70          * 使用RecyclerView,ViewHolder是可以復用的。這根使用ListView的VIewHolder復用是一樣的
 71          * ViewHolder創建的個數好像是可見item的個數+3
 72          */
 73         Log.e("ListAdapter", "onCreateViewHolder");
 74         ItemViewHolder holder = new ItemViewHolder(mInflater.inflate(
 75                 R.layout.item_layout, viewGroup, false));
 76         return holder;
 77     }
 78 
 79     /**
 80      * 向指定位置添加元素
 81      * @param position
 82      * @param value
 83      */
 84     public void add(int position, String value) {
 85         if(position > mDatas.size()) {
 86             position = mDatas.size();
 87         }
 88         if(position < 0) {
 89             position = 0;
 90         }
 91         mDatas.add(position, value);
 92         /**
 93          * 使用notifyItemInserted/notifyItemRemoved會有動畫效果
 94          * 而使用notifyDataSetChanged()則沒有
 95          */
 96         notifyItemInserted(position);
 97     }
 98 
 99     /**
100      * 移除指定位置元素
101      * @param position
102      * @return
103      */
104     public String remove(int position) {
105         if(position > mDatas.size()-1) {
106             return null;
107         }
108         String value = mDatas.remove(position);
109         notifyItemRemoved(position);
110         return value;
111     }
112 
113 
114     public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
115         this.mOnItemClickListener = mOnItemClickListener;
116     }
117 
118     /**
119      * 處理item的點擊事件和長按事件
120      */
121     interface OnItemClickListener {
122         public void onItemClick(View view, int position);
123         public void onItemLongClick(View view, int position);
124     }
125 
126     class ItemViewHolder extends RecyclerView.ViewHolder {
127 
128         private TextView mTextView;
129 
130         public ItemViewHolder(View itemView) {
131             super(itemView);
132             mTextView = (TextView) itemView.findViewById(R.id.textview);
133         }
134     }
135 
136 }
        這里值得注意的是,RecyclerView並沒有提供setOnItemClickListener方法來設置item的點擊事件,所以這里我們自己來實現item的點擊事件,這點很坑爹有木有?沒有就自己設置唄!上面代碼121-124定義了一個點擊接口。然后給Adapter設置定義的接口對象,然后在onBindViewHolder中為每個holder設置點擊事件就行了。但是有一點得注意,因為只要滑動RecyclerView,onBindViewHolder就會不停的調用,如果不加判斷的話,則會不停的創建新的點擊事件對象,浪費內存,所以在設置點擊事件之前需要判斷一下是否已經設置過了(如上面代碼46行),如果設置過了就不需要創建了。
 
item的布局:
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent">
 5     <TextView
 6         android:id="@+id/textview"
 7         android:layout_width="wrap_content"
 8         android:layout_height="48dp"
 9         android:minWidth="48dp"
10         android:gravity="center"
11         android:layout_centerInParent="true"
12         android:text="XXX"/>
13 </RelativeLayout>

 

item分割線:
 1 package com.bbk.lling.recyclerview;
 2 
 3 import android.content.Context;
 4 import android.graphics.Canvas;
 5 import android.graphics.Rect;
 6 import android.graphics.drawable.Drawable;
 7 import android.support.v7.widget.LinearLayoutManager;
 8 import android.support.v7.widget.RecyclerView;
 9 import android.view.View;
10 
11 /**
12  * @Class: ListItemDecoration
13  * @Description: listview的item分割線
14  * @author: lling(www.liuling123.com)
15  * @Date: 2015/10/29
16  */
17 public class ListItemDecoration extends RecyclerView.ItemDecoration {
18 
19     private Drawable mDrawable;
20 
21     private final static int DEFAULT_ORENTATION = LinearLayoutManager.VERTICAL;
22 
23     private int mOrientation;
24 
25     public ListItemDecoration(Context context, int orientation) {
26         if(orientation != LinearLayoutManager.HORIZONTAL && orientation != LinearLayoutManager.VERTICAL) {
27             this.mOrientation = DEFAULT_ORENTATION;
28         } else {
29             this.mOrientation = orientation;
30         }
31         mDrawable = context.getResources().getDrawable(R.drawable.divider);
32     }
33 
34     @Override
35     public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
36         if(mOrientation == LinearLayoutManager.HORIZONTAL) {
37             drawHorizontal(c, parent);
38         } else {
39             drawVertical(c, parent);
40         }
41     }
42 
43     private void drawHorizontal(Canvas c, RecyclerView parent) {
44         int top = parent.getPaddingTop();
45         int bottom = parent.getHeight() - parent.getPaddingBottom();
46 
47         int childCount = parent.getChildCount();
48         for (int i = 0; i < childCount; i++) {
49             View child = parent.getChildAt(i);
50             RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
51                     .getLayoutParams();
52             int left = child.getRight() + params.rightMargin;
53             int right = left + mDrawable.getIntrinsicHeight();
54             mDrawable.setBounds(left, top, right, bottom);
55             mDrawable.draw(c);
56         }
57     }
58 
59     private void drawVertical(Canvas c, RecyclerView parent) {
60         int left = parent.getPaddingLeft();
61         int right = parent.getWidth() - parent.getPaddingRight();
62 
63         int childCount = parent.getChildCount();
64         for (int i = 0; i < childCount; i++) {
65             View child = parent.getChildAt(i);
66             android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
67             RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
68                     .getLayoutParams();
69             int top = child.getBottom() + params.bottomMargin;
70             int bottom = top + mDrawable.getIntrinsicHeight();
71             mDrawable.setBounds(left, top, right, bottom);
72             mDrawable.draw(c);
73         }
74     }
75 
76     @Override
77     public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
78         super.getItemOffsets(outRect, view, parent, state);
79     }
80 }

 

divider.xml:
1 <?xml version="1.0" encoding="utf-8"?>
2 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
3     <size android:height="1dp" android:width="1dp"/>
4     <!--<solid android:color="#e0e0e0"/>-->
5     <solid android:color="#ff0000"/>
6 </shape>
 
好了,ListView的效果已經實現了,看下效果圖
 
 
RecyclerView實現GridView以及瀑布流效果的代碼這里就不貼出來了,demo源碼里面有,需要的可以下載看看。
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM