RecyclerView侧重的是布局的灵活性,虽说可以替代ListView但是连基本的点击事件都没有,这篇文章就来详细讲解如何为RecyclerView的item添加点击事件,顺便复习一下观察者模式。
其实在这篇文章中已经提到如何实现,但是里面有很多不规范的地方,而且没有完整的代码。
最终目的
模拟ListView的setOnItemClickListener()方法,调用者只须调用类似于setOnItemClickListener的东西就能获得被点击item的相关数据。
原理
为RecyclerView的每个子item设置setOnClickListener,然后在onClick中再调用一次对外封装的接口,将这个事件传递给外面的调用者。而“为RecyclerView的每个子item设置setOnClickListener”在Adapter中设置。其实直接在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);
//将创建的View注册点击事件
view.setOnClickListener(this);
returnvh;
}
将点击事件转移给外面的调用者:
@Override
publicvoidonClick(Viewv){
if(mOnItemClickListener!=null){
//注意这里使用getTag方法获取position
mOnItemClickListener.onItemClick(v,(int)v.getTag());
}
}
注意上面调用接口的onItemClick()中的v.getTag()方法,这需要在onBindViewHolder()方法中设置和item的position
@Override
publicvoidonBindViewHolder(ViewHolderviewHolder,intposition){
viewHolder.mTextView.setText(datas[position]);
//将position保存在itemView的Tag中,以便点击时进行获取
viewHolder.itemView.setTag(position);
}
最后暴露给外面的调用者,定义一个设置Listener的方法():
publicvoidsetOnItemClickListener(OnItemClickListenerlistener){
this.mOnItemClickListener=listener;
}
以上所有步骤都发生在自定义的adapter中,典型的观察者模式,有点绕的地方在于,这里涉及到两个观察者模式的使用,view的setOnClickListener本来就是观察者模式,我们将这个观察者模式的事件监听传递给了我们自己的观察者模式。
在Activity中使用
mRecyclerView=(RecyclerView)findViewById(R.id.my_recycler_view);
//创建默认的线性LayoutManager
mLayoutManager=newLinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
mRecyclerView.setHasFixedSize(true);
//创建并设置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);
//将创建的View注册点击事件
view.setOnClickListener(this);
returnvh;
}
@Override
publicvoidonBindViewHolder(ViewHolderviewHolder,intposition){
viewHolder.mTextView.setText(datas[position]);
//将position保存在itemView的Tag中,以便点击时进行获取
viewHolder.itemView.setTag(position);
}
@Override
publicvoidonClick(Viewv){
if(mOnItemClickListener!=null){
//注意这里使用getTag方法获取position
mOnItemClickListener.onItemClick(v,(int)v.getTag());
}
}
publicvoidsetOnItemClickListener(OnItemClickListenerlistener){
this.mOnItemClickListener=listener;
}
//获取数据的数量
@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);
//创建默认的线性LayoutManager
mLayoutManager=newLinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
mRecyclerView.setHasFixedSize(true);
//创建并设置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"/>
总结
在ListView中我们是调用ListView的setOnItemClickListener:
mListView.setOnItemClickListener(newOnItemClickListener(){
publicvoidonItemClick(AdapterViewparent,Viewv,intposition,longid){
...
}
});
而在我们这里是调用mAdapter的setOnItemClickListener。
网友评论