Android RecylerView入門教程
今年Google I/0大會(huì),Google開放了兩個(gè)全新的視圖:RecyclerView和CardView。這篇文章會(huì)提供關(guān)于RecylerView的簡介。
RecylerView作為support-library發(fā)布出來,這對(duì)開發(fā)者來說絕對(duì)是個(gè)好消息。因?yàn)榭梢栽诟偷腁ndroid版本上使用這個(gè)新視圖。下面我們看如何獲取RecylerView。首先打開Android SDK Manager,然后更新Extras->Android Support Library即可。

然后在本地../sdk/extras/android/support/v7中找到recyclerview。我已經(jīng)將下載好的Recyclerview整理成一個(gè)Eclipse可編譯的Library工程上傳到Github,有需求的同學(xué)請(qǐng)戳鏈接。
示例程序
我將通過RecylerView制作一個(gè)橫向滑動(dòng)的“ListView”,下面是示例程序的截圖。并在ActionBar上設(shè)置數(shù)據(jù)的添加/刪除操作。請(qǐng)同學(xué)們注意,RecyclerView的接口Google可能會(huì)繼續(xù)優(yōu)化和修改,所以最終的版本可能和我提供的程序有出入。Demo程序Github鏈接。

為什么要使用RecyclerView?
Google在是這樣描述RecyclerView的:
"A flexible view for providing a limited window into a large data set."
所以RecyclerView適用于無法在一個(gè)屏幕范圍內(nèi)展現(xiàn)格式一樣的數(shù)據(jù)時(shí),需要用多行或多列來展示。例如展示聯(lián)系人,圖片,視頻等。用戶需要滑動(dòng)屏幕來查看數(shù)據(jù),這時(shí)RecyclerView的特性就有用武之地了。比如,當(dāng)用戶滑動(dòng)使當(dāng)前一個(gè)可視的Item滑出屏幕,這個(gè)Item的視圖將會(huì)被回收并在一個(gè)新Item進(jìn)入可視范圍后重新被使用。

如下圖所示,用戶滑動(dòng)向上滑動(dòng)左邊的RecyclerView,No.0和No.1就會(huì)滑出屏幕可視范圍,這時(shí)右圖的No.0和No.1的視圖將會(huì)被RecyclerView放入一個(gè)可重復(fù)利用的緩存中以備再次使用。
可回收利用View是個(gè)很實(shí)用的功能,它不僅可以減少CPU不斷inflate View的開銷,而且可以節(jié)省緩存View的內(nèi)存開銷。
這時(shí),你可能會(huì)問:這不是一個(gè)新功能?。∈堑?,我們已經(jīng)在使用ListView的時(shí)候使用了這個(gè)機(jī)制,但是當(dāng)使用ListView時(shí),顯示,回收等功能是緊密耦合在一起的,Google現(xiàn)在發(fā)布RecyclerView,使方法更靈活,開發(fā)者也能自定義各種各樣的顯示效果。
RecyclerView不再負(fù)責(zé)顯示工作
和ListView不一樣的是,RecyclerView不再負(fù)責(zé)Item的擺放等顯示方面的功能。所有和布局、繪制等方面的工作Google都其拆分成不同的類進(jìn)行管理。所以開發(fā)者可以自定義各種各樣滿足定制需求的的功能類。
下面是一些和RecyclerView相關(guān)的非常重要的類列表。

ViewHolder
關(guān)于ViewHolder,Google早就推薦開發(fā)者使用,但也只是建議。但是現(xiàn)在,RecyclerView.Adapter最終要求開發(fā)者必須使用ViewHolder。如果你還對(duì)ViewHolder不了解,請(qǐng)閱讀Android training session。
Demo通過繼承RecyclerView.ViewHolder來實(shí)現(xiàn)自定義:
public class MyViewHolder extends ViewHolder implements OnClickListener,OnLongClickListener{
public ImageView iv;
public TextView tv;
private MyItemClickListener mListener;
private MyItemLongClickListener mLongClickListener;
public MyViewHolder(View rootView,MyItemClickListener listener,MyItemLongClickListener longClickListener) {
super(rootView);
iv = (ImageView)rootView.findViewById(R.id.item_iv);
tv = (TextView)rootView.findViewById(R.id.item_tv);
this.mListener = listener;
this.mLongClickListener = longClickListener;
rootView.setOnClickListener(this);
rootView.setOnLongClickListener(this);
}
/**
* 點(diǎn)擊監(jiān)聽
*/
@Override
public void onClick(View v) {
if(mListener != null){
mListener.onItemClick(v,getPosition());
}
}
/**
* 長按監(jiān)聽
*/
@Override
public boolean onLongClick(View arg0) {
if(mLongClickListener != null){
mLongClickListener.onItemLongClick(arg0, getPosition());
}
return true;
}
}
RecyclerView.Adapter
Adapter負(fù)責(zé)扮演兩個(gè)角色:不僅為底部數(shù)據(jù)提供支持而且還負(fù)責(zé)為數(shù)據(jù)創(chuàng)建合適的視圖。Adapter適用在Android很多控件,例如ListView、AutoCompleteTextView等。
繼承RecyclerView.Adapter需要實(shí)現(xiàn)以下三個(gè)方法:
public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType)
public void onBindViewHolder(ViewHolder holder,int position)
public int getItemCount()
Demo中的Adapter:
[java] view plain copy
public class MyAdapter extends Adapter<MyViewHolder> {
private List<MyItemBean> mData;
private MyItemClickListener mItemClickListener;
private MyItemLongClickListener mItemLongClickListener;
public MyAdapter(List<MyItemBean> data){
this.mData = data;
}
@Override
public int getItemCount() {
return mData.size();
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
MyItemBean bean = mData.get(position);
holder.tv.setText(bean.tv);
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent,false);
MyViewHolder vh = new MyViewHolder(itemView,mItemClickListener,mItemLongClickListener);
return vh;
}
}
onCreateViewHolder中負(fù)責(zé)為Item創(chuàng)建視圖,onBindViewHolder負(fù)責(zé)將數(shù)據(jù)綁定到Item的視圖上。
RecyclerView.LayoutManager
LayoutManager是RecyclerView中最有意思的類。該類負(fù)責(zé)將每個(gè)Item視圖在RecylerView中的布局。目前Google提供了LayoutManager的一個(gè)子類:LinearLayoutManager。LinearLayoutManager提供了橫向和豎向兩種布局,Demo就是使用LinearLayoutManger的橫向布局實(shí)現(xiàn)的。
如果要自定義LayoutManager,需要實(shí)現(xiàn)一個(gè)abstract方法
public LayoutParams generateDefaultLayoutParams()
Demo中為RecylerView添加LinearLayoutManager的片段:
MyLayoutManager manager = new MyLayoutManager(this);
manager.setOrientation(LinearLayout.HORIZONTAL);//默認(rèn)是LinearLayout.VERTICAL
mRecyclerView.setLayoutManager(manager);
LinearLayoutManager提供了如下幾個(gè)方法來幫助開發(fā)者獲取屏幕上的頂部item和底部item:
findFirstVisibleItemPosition()
findFirstCompletelyVisibleItemPosition()
findLastVisibleItemPosition()
findLastCompletelyVisibleItemPosition()
RecyclerView.ItemDecoration
通過ItemDecoration可以使各個(gè)Item在視覺上相互分開,其實(shí)和ListView的Divider很像。ItemDecoration并不是RecyclerView必須設(shè)置的,開發(fā)者可以不設(shè)置或者設(shè)置多個(gè)Decoration。RecyclerView會(huì)遍歷所有的ItemDecoration并調(diào)用各自的繪圖方法。
繼承ItemDecoration需要實(shí)現(xiàn)以下三個(gè)方法:
public void onDraw(Canvas c,RecyclerView parent,RecyclerView.State state)
public void getItemOffset(Rect outRect,int itemPosition,RecyclerView parent)
LayoutManager會(huì)調(diào)用getItemOffset方法來計(jì)算每個(gè)Item的Decoration合適的尺寸。
Demo中自定義了一個(gè)ItemDecoration來實(shí)現(xiàn)ListView的Divider效果:
public class MyDecoration extends ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
private Drawable mDivider;
public MyDecoration(Context ctx){
final TypedArray a = ctx.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
}
@Override
public void onDraw(Canvas c, RecyclerView parent, State state) {
int top = parent.getPaddingTop();
int bottom = parent.getHeight() - parent.getPaddingBottom();
int childCount = parent.getChildCount();
for(int i=0;i < childCount;i++){
View child = parent.getChildAt(i);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams)child.getLayoutParams();
int left = child.getRight() + layoutParams.rightMargin;
int right = left + mDivider.getIntrinsicWidth();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
State state) {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
RecyclerView.ItemAnimatior
當(dāng)Item有以下三種操作時(shí)ItemAnimatior會(huì)為RecyclerView提供動(dòng)畫效果:
刪除某一個(gè)Item
添加一個(gè)新的Item
移動(dòng)某個(gè)Item
Google提供了一個(gè)名為DefaultItemAnimator的默認(rèn)ItemAnimator供開發(fā)者使用。如果開發(fā)者不為RecyclerView設(shè)置ItemAnimator,RecyclerView也會(huì)使用默認(rèn)的DefaultItemAnimator。
顯然,為了讓動(dòng)畫效果起效,開發(fā)者必須通知Adapter數(shù)據(jù)有改變。之前我們使用Adapter時(shí)會(huì)調(diào)用notifyDataSetChanged()來通知Adapter數(shù)據(jù)改變并更新視圖,現(xiàn)在RecyclerView,Adapter提供了許多notifyXyz()方法,例如Demo中使用了以下兩個(gè)方法:
public final void notifyItemInserted(int position)
public final void notifyItemRemoved(int position)
使用RecyclerView
首先,我們先看如何在xml中使用RecyclerView
<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.xmy.recylerviewdemo.MainActivity" > <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
然后需要開發(fā)者在代碼中實(shí)現(xiàn)RecyclerView的組裝,大體可概括為以下步驟:
實(shí)例化RecyclerView
為RecyclerView設(shè)置LayoutManager
為RecyclerView設(shè)置Adapater
如果有需求,可以設(shè)置一個(gè)或多個(gè)ItemDecorations,當(dāng)然,也可以不設(shè)置
如果有需求,可以設(shè)置ItemAnimator
- Android使用Recyclerview實(shí)現(xiàn)圖片水平自動(dòng)循環(huán)滾動(dòng)效果
- Android_RecyclerView實(shí)現(xiàn)上下滾動(dòng)廣告條實(shí)例(帶圖片)
- Android中RecyclerView實(shí)現(xiàn)分頁滾動(dòng)的方法詳解
- Android RecyclerView滾動(dòng)定位
- Android使用RecyclerView實(shí)現(xiàn)水平滾動(dòng)控件
- Android代碼實(shí)現(xiàn)AdapterViews和RecyclerView無限滾動(dòng)
- 功能強(qiáng)大的Android滾動(dòng)控件RecyclerView
相關(guān)文章
Android自定義ViewGroup實(shí)現(xiàn)朋友圈九宮格控件
在我們的實(shí)際應(yīng)用中,經(jīng)常需要用到自定義控件,比如自定義圓形頭像,自定義計(jì)步器等等,這篇文章主要給大家介紹了關(guān)于Android自定義ViewGroup實(shí)現(xiàn)朋友圈九宮格控件的相關(guān)資料,需要的朋友可以參考下2021-07-07
Android Listview點(diǎn)贊問題關(guān)于圖片重復(fù)問題
最近在開發(fā)android方面的項(xiàng)目時(shí),遇到很多問題,下面小編以listview 與 baseadapter結(jié)合使用為例,給大家分享下關(guān)于點(diǎn)贊的的時(shí)候 圖片重復(fù)問題的解決方法,一起看看吧2016-11-11
Android中創(chuàng)建快捷方式及刪除快捷方式實(shí)現(xiàn)方法
這篇文章主要介紹了Android中創(chuàng)建快捷方式及刪除快捷方式實(shí)現(xiàn)方法,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-06-06
深入剖析Android系統(tǒng)中Service和IntentService的區(qū)別
這篇文章主要介紹了Android系統(tǒng)中Service和IntentService的區(qū)別,與普通的服務(wù)相比,IntentService可以開啟單獨(dú)的線程來處理intent請(qǐng)求,需要的朋友可以參考下2016-04-04
Android 2.3 撥號(hào)上網(wǎng)流程從源碼角度進(jìn)行分析
SIM卡實(shí)現(xiàn)撥號(hào)上網(wǎng)功能之前需要設(shè)置一番,這些設(shè)置步驟究竟做了哪些事情呢?我們現(xiàn)在就從源碼的角度進(jìn)行分析2013-01-01

