RecyclerView側(cè)重的是布局的靈活性耘斩,雖說可以替代ListView但是連基本的點擊事件都沒有范嘱,這篇文章就來詳細(xì)講解如何為RecyclerView的item添加點擊事件,順便復(fù)習(xí)一下觀察者模式曹抬。
其實在這篇文章中已經(jīng)提到如何實現(xiàn)材部,但是里面有很多不規(guī)范的地方寝贡,而且沒有完整的代碼。
最終目的
模擬ListView的setOnItemClickListener()方法兵睛,調(diào)用者只須調(diào)用類似于setOnItemClickListener的東西就能獲得被點擊item的相關(guān)數(shù)據(jù)肯骇。
原理
為RecyclerView的每個子item設(shè)置setOnClickListener窥浪,然后在onClick中再調(diào)用一次對外封裝的接口,將這個事件傳遞給外面的調(diào)用者笛丙。而“為RecyclerView的每個子item設(shè)置setOnClickListener”在Adapter中設(shè)置漾脂。其實直接在onClick中也能完全處理item的點擊事件,但是這樣會破壞代碼的邏輯胚鸯。
步驟
adapter中
自定義一個繼承自RecyclerView.Adapter的MyAdapter骨稿。
1.在MyAdapter中定義如下接口,模擬ListView的OnItemClickListener:
//define?interface
publicstaticinterfaceOnItemClickListener{
voidonItemClick(Viewview,intposition);
}
聲明一個這個接口的變量
privateOnItemClickListenermOnItemClickListener=null;
在onCreateViewHolder()中為每個item添加點擊事件
@Override
publicViewHolderonCreateViewHolder(ViewGroupviewGroup,intviewType){
Viewview=LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item,viewGroup,false);
ViewHoldervh=newViewHolder(view);
//將創(chuàng)建的View注冊點擊事件
view.setOnClickListener(this);
returnvh;
}
將點擊事件轉(zhuǎn)移給外面的調(diào)用者:
@Override
publicvoidonClick(Viewv){
if(mOnItemClickListener!=null){
//注意這里使用getTag方法獲取position
mOnItemClickListener.onItemClick(v,(int)v.getTag());
}
}
注意上面調(diào)用接口的onItemClick()中的v.getTag()方法,這需要在onBindViewHolder()方法中設(shè)置和item的position
@Override
publicvoidonBindViewHolder(ViewHolderviewHolder,intposition){
viewHolder.mTextView.setText(datas[position]);
//將position保存在itemView的Tag中姜钳,以便點擊時進(jìn)行獲取
viewHolder.itemView.setTag(position);
}
最后暴露給外面的調(diào)用者坦冠,定義一個設(shè)置Listener的方法():
publicvoidsetOnItemClickListener(OnItemClickListenerlistener){
this.mOnItemClickListener=listener;
}
以上所有步驟都發(fā)生在自定義的adapter中,典型的觀察者模式哥桥,有點繞的地方在于辙浑,這里涉及到兩個觀察者模式的使用,view的setOnClickListener本來就是觀察者模式拟糕,我們將這個觀察者模式的事件監(jiān)聽傳遞給了我們自己的觀察者模式判呕。
在Activity中使用
mRecyclerView=(RecyclerView)findViewById(R.id.my_recycler_view);
//創(chuàng)建默認(rèn)的線性LayoutManager
mLayoutManager=newLinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//如果可以確定每個item的高度是固定的,設(shè)置這個選項可以提高性能
mRecyclerView.setHasFixedSize(true);
//創(chuàng)建并設(shè)置Adapter
mAdapter=newMyAdapter(data);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(newOnItemClickListener(){
@Override
publicvoidonItemClick(Viewview,intposition){
Toast.makeText(MainActivity.this,data[position],600).show();
}
});
完整代碼
MyAdapter.java
packagecom.example.recyclerviewdemo;
importandroid.support.v7.widget.RecyclerView;
importandroid.util.Log;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.TextView;
publicclassMyAdapterextendsRecyclerView.AdapterimplementsView.OnClickListener{
privateString[]datas;
publicMyAdapter(String[]datas){
this.datas=datas;
}
privateOnItemClickListenermOnItemClickListener=null;
//define?interface
publicstaticinterfaceOnItemClickListener{
voidonItemClick(Viewview,intposition);
}
@Override
publicViewHolderonCreateViewHolder(ViewGroupviewGroup,intviewType){
Viewview=LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item,viewGroup,false);
ViewHoldervh=newViewHolder(view);
//將創(chuàng)建的View注冊點擊事件
view.setOnClickListener(this);
returnvh;
}
@Override
publicvoidonBindViewHolder(ViewHolderviewHolder,intposition){
viewHolder.mTextView.setText(datas[position]);
//將position保存在itemView的Tag中送滞,以便點擊時進(jìn)行獲取
viewHolder.itemView.setTag(position);
}
@Override
publicvoidonClick(Viewv){
if(mOnItemClickListener!=null){
//注意這里使用getTag方法獲取position
mOnItemClickListener.onItemClick(v,(int)v.getTag());
}
}
publicvoidsetOnItemClickListener(OnItemClickListenerlistener){
this.mOnItemClickListener=listener;
}
//獲取數(shù)據(jù)的數(shù)量
@Override
publicintgetItemCount(){
returndatas.length;
}
//自定義的ViewHolder侠草,持有每個Item的的所有界面元素
publicstaticclassViewHolderextendsRecyclerView.ViewHolder{
publicTextViewmTextView;
publicViewHolder(Viewview){
super(view);
mTextView=(TextView)view.findViewById(R.id.text);
}
}
}
item.xml
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="50dip"
>
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
MainActivity.java
packagecom.example.recyclerviewdemo;
importcom.example.recyclerviewdemo.MyAdapter.OnItemClickListener;
importandroid.support.v7.app.ActionBarActivity;
importandroid.support.v7.widget.LinearLayoutManager;
importandroid.support.v7.widget.RecyclerView;
importandroid.os.Bundle;
importandroid.view.Menu;
importandroid.view.MenuItem;
importandroid.view.View;
importandroid.widget.Toast;
publicclassMainActivityextendsActionBarActivity{
privateRecyclerViewmRecyclerView;
privateLinearLayoutManagermLayoutManager;
privateMyAdaptermAdapter;
privateString[]data=newString[]{"aa","bb","aa","bb","aa","bb","aa","bb","aa","bb","aa","bb","aa","bb","aa","bb","aa","bb","aa","bb"};
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView=(RecyclerView)findViewById(R.id.my_recycler_view);
//創(chuàng)建默認(rèn)的線性LayoutManager
mLayoutManager=newLinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//如果可以確定每個item的高度是固定的,設(shè)置這個選項可以提高性能
mRecyclerView.setHasFixedSize(true);
//創(chuàng)建并設(shè)置Adapter
mAdapter=newMyAdapter(data);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(newOnItemClickListener(){
@Override
publicvoidonItemClick(Viewview,intposition){
Toast.makeText(MainActivity.this,data[position],600).show();
}
});
}
@Override
publicbooleanonCreateOptionsMenu(Menumenu){
//?Inflate?the?menu;?this?adds?items?to?the?action?bar?if?it?is?present.
getMenuInflater().inflate(R.menu.main,menu);
returntrue;
}
@Override
publicbooleanonOptionsItemSelected(MenuItemitem){
//?Handle?action?bar?item?clicks?here.?The?action?bar?will
//?automatically?handle?clicks?on?the?Home/Up?button,?so?long
//?as?you?specify?a?parent?activity?in?AndroidManifest.xml.
intid=item.getItemId();
if(id==R.id.action_settings){
returntrue;
}
returnsuper.onOptionsItemSelected(item);
}
}
activity_main.xml
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
android:id="@+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"/>
總結(jié)
在ListView中我們是調(diào)用ListView的setOnItemClickListener:
mListView.setOnItemClickListener(newOnItemClickListener(){
publicvoidonItemClick(AdapterViewparent,Viewv,intposition,longid){
...
}
});
而在我們這里是調(diào)用mAdapter的setOnItemClickListener累澡。