首先主activity的布局檔案:
<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" >
<android.support.v7.widget.recyclerview
android:id="@+id/id_recyclerview_horizontal"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_centervertical="true"
android:background="#ff0000"
android:scrollbars="none" />
</relativelayout>
item的布局檔案:
<?xml version="1.0" encoding="utf-8"?>
android:layout_width="120dp"
android:layout_height="120dp"
android:background="@drawable/item_bg02" >
<imageview
android:id="@+id/id_index_gallery_item_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_alignparenttop="true"
android:layout_centerhorizontal="true"
android:layout_margin="5dp"
android:scaletype="centercrop" />
<textview
android:id="@+id/id_index_gallery_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/id_index_gallery_item_image"
android:layout_marginbottom="5dp"
android:layout_margintop="5dp"
android:textcolor="#ff0000"
android:text="some info"
android:textsize="12dp" />
資料擴充卡:
package com.example.zhy_horizontalscrollview03;
import java.util.list;
import android.content.context;
import android.support.v7.widget.recyclerview;
import android.view.layoutinflater;
import android.view.view;
import android.view.viewgroup;
import android.widget.imageview;
import android.widget.textview;
public class galleryadapter extends
recyclerview.adapter<galleryadapter.viewholder>
{
private layoutinflater minflater;
private list<integer> mdatas;
public galleryadapter(context context, list<integer> datats)
{
minflater = layoutinflater.from(context);
mdatas = datats;
}
public static class viewholder extends recyclerview.viewholder
public viewholder(view arg0)
{
super(arg0);
}
imageview mimg;
textview mtxt;
@override
public int getitemcount()
return mdatas.size();
/**
* 建立viewholder
*/
public viewholder oncreateviewholder(viewgroup viewgroup, int i)
view view = minflater.inflate(r.layout.activity_index_gallery_item,
viewgroup, false);
viewholder viewholder = new viewholder(view);
viewholder.mimg = (imageview) view
.findviewbyid(r.id.id_index_gallery_item_image);
return viewholder;
* 設定值
public void onbindviewholder(final viewholder viewholder, final int i)
viewholder.mimg.setimageresource(mdatas.get(i));
}
可以看到資料擴充卡與baseadapter比較發生了相當大的變化,主要有3個方法:
getitemcount 這個不用說,擷取總的條目數
oncreateviewholder 建立viewholder
onbindviewholder 将資料綁定至viewholder
可見,recyclerview對viewholder也進行了一定的封裝,但是如果你仔細觀察,你會發出一個疑問,listview裡面有個getview傳回view為item的布局,那麼這個item的樣子在哪控制?
其實是這樣的,我們建立的viewholder必須繼承recyclerview.viewholder,這個recyclerview.viewholder的構造時必須傳入一個view,這個view相當于我們listview getview中的convertview (即:我們需要inflate的item布局需要傳入)。
還有一點,listview中convertview是複用的,在recyclerview中,是把viewholder作為緩存的機關了,然後convertview作為viewholder的成員變量保持在viewholder中,也就是說,假設沒有螢幕顯示10個條目,則會建立10個viewholder緩存起來,每次複用的是viewholder,是以他把getview這個方法變為了oncreateviewholder。有興趣的自己列印下log,測試下。
最後在activity中使用:
import java.util.arraylist;
import java.util.arrays;
import android.app.activity;
import android.os.bundle;
import android.support.v7.widget.linearlayoutmanager;
import android.view.window;
public class mainactivity extends activity
private recyclerview mrecyclerview;
private galleryadapter madapter;
protected void oncreate(bundle savedinstancestate)
super.oncreate(savedinstancestate);
requestwindowfeature(window.feature_no_title);
setcontentview(r.layout.activity_main);
initdatas();
//得到控件
mrecyclerview = (recyclerview) findviewbyid(r.id.id_recyclerview_horizontal);
//設定布局管理器
linearlayoutmanager linearlayoutmanager = new linearlayoutmanager(this);
linearlayoutmanager.setorientation(linearlayoutmanager.horizontal);
mrecyclerview.setlayoutmanager(linearlayoutmanager);
//設定擴充卡
madapter = new galleryadapter(this, mdatas);
mrecyclerview.setadapter(madapter);
private void initdatas()
mdatas = new arraylist<integer>(arrays.aslist(r.drawable.a,
r.drawable.b, r.drawable.c, r.drawable.d, r.drawable.e,
r.drawable.f, r.drawable.g, r.drawable.h, r.drawable.l));
使用起來也很友善,唯一的差別就是要設定layoutmanager,目前隻有一個實作類,就是linearlayoutmanager,可以設定為水準或者垂直。
最後效果圖:

效果很不錯,這就是recyclerview的基本用法了,但是你會發現一個坑爹的地方,竟然沒有提供setonitemclicklistener這個回調,要不要這麼坑爹。。。
雖然它沒有提供,但是添加個onitemclicklistener對我們來說還不是小菜一碟~
我決定在adapter中添加這個回調接口:
import android.view.view.onclicklistener;
* itemclick的回調接口
* @author zhy
*
public interface onitemclicklitener
void onitemclick(view view, int position);
private onitemclicklitener monitemclicklitener;
public void setonitemclicklitener(onitemclicklitener monitemclicklitener)
this.monitemclicklitener = monitemclicklitener;
//如果設定了回調,則設定點選事件
if (monitemclicklitener != null)
viewholder.itemview.setonclicklistener(new onclicklistener()
{
@override
public void onclick(view v)
{
monitemclicklitener.onitemclick(viewholder.itemview, i);
}
});
很簡單,建立一個接口,提供一個設定入口,然後在onbindviewholder中判斷即可。
最後在主activity中設定監聽:
madapter = new galleryadapter(this, mdatas);
madapter.setonitemclicklitener(new onitemclicklitener()
public void onitemclick(view view, int position)
toast.maketext(mainactivity.this, position+"", toast.length_short)
.show();
});
mrecyclerview.setadapter(madapter);
好了,這樣就行了,看效果圖:
效果還是不錯的,接下來我想改成相冊效果,即上面顯示一張大圖,下面的recyclerview做為圖檔切換的訓示器。
首先修改下布局:
布局檔案:
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:orientation="vertical" >
<framelayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<imageview
android:id="@+id/id_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:layout_margin="10dp"
android:scaletype="centercrop"
android:src="@drawable/ic_launcher" />
</framelayout>
<com.example.zhy_horizontalscrollview03.myrecyclerview
android:layout_gravity="bottom"
</linearlayout>
添加一個顯示大圖的區域,把recyclerview改為自己定義的。
然後看我們自定義recyclerview的代碼:
import android.util.attributeset;
import android.view.motionevent;
public class copyofmyrecyclerview extends recyclerview
public copyofmyrecyclerview(context context, attributeset attrs)
super(context, attrs);
private view mcurrentview;
* 滾動時回調的接口
private onitemscrollchangelistener mitemscrollchangelistener;
public void setonitemscrollchangelistener(
onitemscrollchangelistener mitemscrollchangelistener)
this.mitemscrollchangelistener = mitemscrollchangelistener;
public interface onitemscrollchangelistener
void onchange(view view, int position);
protected void onlayout(boolean changed, int l, int t, int r, int b)
super.onlayout(changed, l, t, r, b);
mcurrentview = getchildat(0);
if (mitemscrollchangelistener != null)
mitemscrollchangelistener.onchange(mcurrentview,
getchildposition(mcurrentview));
public boolean ontouchevent(motionevent e)
if (e.getaction() == motionevent.action_move)
mcurrentview = getchildat(0);
// log.e("tag", getchildposition(getchildat(0)) + "");
if (mitemscrollchangelistener != null)
mitemscrollchangelistener.onchange(mcurrentview,
getchildposition(mcurrentview));
}
return super.ontouchevent(e);
定義了一個滾動時回調的接口,然後在ontouchevent中,監聽action_move,使用者手指滑動時,不斷把目前第一個view回調回去~
關于我咋知道getchildat(0)和getchildposition()可用,起初我以為有getfirstvisibleitem這個方法,後來發現麼有;但是發現了getrecycledviewpool()看名字我覺得是viewholder那個緩存隊列,我想那麼直接取這個隊列的第一個不就是我要的view麼,後來沒有成功。我就觀察它内部的view,最後發現,第一個顯示的始終是它第一個child,至于getchildposition這個看方法就看出來了。
現在的效果:
和我之前那個例子的效果是一模一樣的,不過,我還想做一些改變,我覺得gallery或者說相冊的訓示器,下面可能1000來張圖檔,我不僅喜歡手指在螢幕上滑動時,圖檔會自動切換。我還希望,如果我給訓示器一個加速度,即使手指離開,下面還在滑動,上面也會關聯 。而且我還想做些優化,直接在action_move中回調,觸發的頻率太高了,理論上一張圖檔隻會觸發一次~~
既然希望手指離開還能關聯,那麼不僅需要action_move需要監聽,還得監聽一個加速度,速度到達一定值,然後繼續移動~~再理一理,需要這麼麻煩麼,不是能滾動麼,那麼應該有onscrolllistener啊,小看一把,果然有,哈哈哈~天助我也,下面看修改後的代碼:
import android.support.v7.widget.recyclerview.onscrolllistener;
public class myrecyclerview extends recyclerview implements onscrolllistener
* 記錄目前第一個view
public myrecyclerview(context context, attributeset attrs)
// todo auto-generated constructor stub
this.setonscrolllistener(this);
public void onscrollstatechanged(int arg0)
*
* 滾動時,判斷目前第一個view是否發生變化,發生才回調
public void onscrolled(int arg0, int arg1)
view newview = getchildat(0);
if (newview != null && newview != mcurrentview)
mcurrentview = newview ;
我放棄了重寫ontouchevent方法,而是讓這個類實作recyclerview.onscrolllistener接口,然後設定監聽,在onscrolled裡面進行判斷。
至于優化:我使用了一個成員變化存儲目前第一個view,隻有第一個view發生變化時才回調~~太完美了~
看mainactivity:
import android.widget.toast;
import com.example.zhy_horizontalscrollview03.galleryadapter.onitemclicklitener;
import com.example.zhy_horizontalscrollview03.myrecyclerview.onitemscrollchangelistener;
private myrecyclerview mrecyclerview;
private imageview mimg ;
mimg = (imageview) findviewbyid(r.id.id_content);
mrecyclerview = (myrecyclerview) findviewbyid(r.id.id_recyclerview_horizontal);
mrecyclerview.setonitemscrollchangelistener(new onitemscrollchangelistener()
@override
public void onchange(view view, int position)
mimg.setimageresource(mdatas.get(position));
};
});
madapter.setonitemclicklitener(new onitemclicklitener()
public void onitemclick(view view, int position)
// toast.maketext(getapplicationcontext(), position + "", toast.length_short)
// .show();
代碼沒什麼變化~多了個設定回調~
效果圖:
可以看到不僅支援手機在上面移動時的變化,如果我給了一個加速度,下面持續滾動,上面也會持續變化~~大贊~每張圖檔回調一次,效率也相當不錯。
好了,看完這邊部落格,相信大家對于recyclerview有了一定的認識,甚至對于如何改造一個控件也多了一份了解~~
如果覺得不錯,就留個言或者點個贊,表示對我的支援
<a target="_blank" href="http://download.csdn.net/detail/lmj623565791/7684029">源碼點選下載下傳</a>
<a target="_blank" href="http://download.csdn.net/detail/lmj623565791/7684029"></a>