這篇文章是根據官網的一篇文章(這裏)寫的,不過作者增加了一些自己的理解,我十分推崇這種方式,而不是死板的翻譯官網的文檔,國內技術文章翻譯的最差的地方在於:翻譯出來的句子還保留着英語的語序。
RecyclerView 是Android L版本中新添加的一個用來取代ListView的SDK,它的靈活性與可替代性比listview更好。接下來通過一系列的文章講解如何使用RecyclerView,徹底拋棄ListView.
介紹
RecyclerView與ListView原理是類似的:都是僅僅維護少量的View並且可以展示大量的數據集。RecyclerView用以下兩種方式簡化了數據的展示和處理:
-
使用LayoutManager來確定每一個item的排列方式。
-
爲增加和刪除項目提供默認的動畫效果。
你也可以定義你自己的LayoutManager和添加刪除動畫,RecyclerView項目結構如下:
-
Adapter:使用RecyclerView之前,你需要一個繼承自RecyclerView.Adapter的適配器,作用是將數據與每一個item的界面進行綁定。
-
LayoutManager:用來確定每一個item如何進行排列擺放,何時展示和隱藏。回收或重用一個View的時候,LayoutManager會向適配器請求新的數據來替換舊的數據,這種機制避免了創建過多的View和頻繁的調用findViewById方法(與ListView原理類似)。
目前SDK中提供了三種自帶的LayoutManager:
-
LinearLayoutManager
-
GridLayoutManager
-
StaggeredGridLayoutManager
第一節、簡單的RecyclerView使用方法
本節所示示例是一個最簡單的使用方法,在接下來幾節中將會介紹更多RecyclerView的別的一些屌爆的用法。作者用的環境是Android Studio 0.8.6。
1、添加依賴
在AS的build.gradle
中添加依賴,然後同步一下就可以引入依賴包:
1
2
3
4
|
dependencies { ... compile 'com.android.support:recyclerview-v7:21.0.+' } |
2、編寫代碼
添加完依賴之後,就開始寫代碼了,與ListView用法類似,也是先在xml佈局文件中創建一個RecyclerView的佈局:
1
2
3
4
5
6
7
8
9
10
11
|
<RelativeLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "match_parent" android:layout_height= "match_parent" tools:context= ".MainActivity" > <android.support.v7.widget.RecyclerView android:id= "@+id/my_recycler_view" android:layout_width= "match_parent" android:layout_height= "match_parent" android:scrollbars= "vertical" /> </RelativeLayout> |
創建完佈局之後在MainActivity中獲取這個RecyclerView,並聲明LayoutManager
與Adapter
,代碼如下:
1
2
3
4
5
6
7
8
9
|
mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view); //創建默認的線性LayoutManager mLayoutManager = new LinearLayoutManager( this ); mRecyclerView.setLayoutManager(mLayoutManager); //如果可以確定每個item的高度是固定的,設置這個選項可以提高性能 mRecyclerView.setHasFixedSize( true ); //創建並設置Adapter mAdapter = newMyAdapter(getDummyDatas()); mRecyclerView.setAdapter(mAdapter); |
接下來的問題就是Adapter的創建:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { public String[] datas = null ; public MyAdapter(String[] datas) { this .datas = datas; } //創建新View,被LayoutManager所調用 @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item,viewGroup, false ); ViewHolder vh = new ViewHolder(view); return vh; } //將數據與界面進行綁定的操作 @Override public void onBindViewHolder(ViewHolder viewHolder, int position) { viewHolder.mTextView.setText(datas[position]); } //獲取數據的數量 @Override public int getItemCount() { return datas.length; } //自定義的ViewHolder,持有每個Item的的所有界面元素 public static class ViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public ViewHolder(View view){ super (view); mTextView = (TextView) view.findViewById(R.id.text); } } } |
3、運行
寫完這些代碼這個例子既可以跑起來了。從例子也可以看出來,RecyclerView的用法並不比ListView複雜,反而更靈活好用,它將數據、排列方式、數據的展示方式都分割開來,因此可定製型,自定義的形式也非常多,非常靈活。
橫向佈局
如果想要一個橫向的List只要設置LinearLayoutManager如下就行,注意要聲明mLayoutManager的類型是LinearLayoutManager而不是父類LayoutManager:
1
|
mLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); |
Grid佈局
如果想要一個Grid佈局的列表,只要聲明LayoutManager爲GridLayoutManager即可:
1
2
|
mLayoutManager = new GridLayoutManager(context,columNum); mRecyclerView.setLayoutManager(mLayoutManager); |
注意,在Grid佈局中也可以設置列表的Orientation屬性,來實現橫向和縱向的Grid佈局。
瀑布流佈局
瀑布流就使用StaggeredGridLayoutManager吧,具體方法與上面類似,就不做介紹啦。
總結
本節介紹的是一個最最簡單的RecyclerView的使用方法,後面將介紹一些更高級的用法。
第二節、RecyclerView的高級方法
當使用了一段時間的RecyclerView,發現爲其每一項添加點擊事件並沒有ListView那麼輕鬆,像ListView直接加個OnItemClickListener就行了。實際上我們不要把RecyclerView當做ListView的一個升級版,希望大家把他看做一個容器,同時裏面包含了很多不同的Item,它們可以以不同方式排列組合,非常靈活,點擊方式你可以按照你自己的意願進行實現。
本節主要講解如何爲RecyclerView添加點擊事件, 並簡單介紹如何進行Item增加刪除。
添加點擊事件
上一節中我們講了如何使用RecyclerView的Adpater,其實我們會發現,Adapter是添加點擊事件一個很好的地方,裏面是構造佈局等View的主要場所,也是數據和佈局進行綁定的地方。首先我們在Adapter中創建一個實現點擊接口,其中view是點擊的Item,data是我們的數據,因爲我們想知道我點擊的區域部分的數據是什麼,以便我下一步進行操作:
1
2
3
|
public static interface OnRecyclerViewItemClickListener { void onItemClick(View view , DataModel data); } |
定義完接口,添加接口和設置Adapter接口的方法:
1
2
3
4
|
private OnRecyclerViewItemClickListener mOnItemClickListener = null ; public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) { this .mOnItemClickListener = listener; } |
那麼這個接口用在什麼地方呢?如下代碼所示,我們爲Adapter實現OnClickListener方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{ @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, final int i) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false ); ViewHolder vh = new ViewHolder(view); //將創建的View註冊點擊事件 view.setOnClickListener( this ); return vh; } @Override public void onBindViewHolder(ViewHolder viewHolder, final int i) { viewHolder.mTextView.setText(datas.get(i).title); //將數據保存在itemView的Tag中,以便點擊時進行獲取 viewHolder.itemView.setTag(datas.get(i)); } ... @Override public void onClick(View v) { if (mOnItemClickListener != null ) { //注意這裏使用getTag方法獲取數據 mOnItemClickListener.onItemClick(v,(DataModel)v.getTag()); } } ... } |
做完這些事情,我們就可以在Activity或其他地方爲RecyclerView添加項目點擊事件了,如在MainActivity中:
1
2
3
4
5
6
7
8
|
mAdapter = new MyAdapter(getDummyDatas()); mRecyclerView.setAdapter(mAdapter); mAdapter.setOnItemClickListener( new MyAdapter.OnRecyclerViewItemClickListener() { @Override public void onItemClick(View view, DataModel data) { //DO your fucking bussiness here! } }); |
完成了以上代碼就可以爲RecyclerView添加項目點擊事件了,下面我們來看看RecyclerView如何添加和刪除數據並在界面上顯示。
添加刪除數據
以前在ListView當中,我們只要修改後數據用Adapter的notifyDatasetChange一下就可以更新界面。然而在RecyclerView中還有一些更高級的用法:
添加數據:
1
2
3
4
|
public void addItem(DataModel content, int position) { datas.add(position, content); notifyItemInserted(position); //Attention! } |
刪除數據:
1
2
3
4
5
|
public void removeItem(DataModel model) { int position = datas.indexOf(model); datas.remove(position); notifyItemRemoved(position); //Attention! } |
值得注意的是RecyclerView的添加刪除都是有默認的動畫效果的,如果沒有效果可以添加如下代碼:
1
|
mRecyclerView.setItemAnimator(newDefaultItemAnimator()); |
當然啦你也可以自己定義你自己的Animator,等我研究明白了也來講一講如何自定義這些效果~