为RecyclerView添加item的点击事件

原文链接:泡在网上的日子

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:

 
 
  1.     //define interface
  2.     public static interface OnRecyclerViewItemClickListener {
  3.         void onItemClick(View view , String data);
  4.     }


声明一个这个接口的变量

 
 
  1.     private OnRecyclerViewItemClickListener mOnItemClickListener = null;

在onCreateViewHolder()中为每个item添加点击事件

 
 
  1.     @Override
  2.     public ViewHolder onCreateViewHolder(ViewGroup viewGroup,  int viewType) {
  3.         View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
  4.         ViewHolder vh = new ViewHolder(view);
  5.         //将创建的View注册点击事件
  6.         view.setOnClickListener(this);
  7.         return vh;
  8.     }

将点击事件转移给外面的调用者:

 
 
  1.     @Override
  2.     public void onClick(View v) {
  3.         if (mOnItemClickListener != null) {
  4.             //注意这里使用getTag方法获取数据
  5.             mOnItemClickListener.onItemClick(v,(String)v.getTag());
  6.         }
  7.     }

注意上面调用接口的onItemClick()中的v.getTag()方法,这需要在onBindViewHolder()方法中设置和item相关的数据

 
 
  1.     @Override
  2.     public void onBindViewHolder(ViewHolder viewHolder,  int position) {
  3.         viewHolder.mTextView.setText(datas[position]);
  4.         //将数据保存在itemView的Tag中,以便点击时进行获取
  5.         viewHolder.itemView.setTag(datas[position]);
  6.     }

最后暴露给外面的调用者,定义一个设置Listener的方法():

 
 
  1.     public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
  2.         this.mOnItemClickListener = listener;
  3.     }

以上所有步骤都发生在自定义的adapter中,典型的观察者模式,有点绕的地方在于,这里涉及到两个观察者模式的使用,view的setOnClickListener本来就是观察者模式,我们将这个观察者模式的事件监听传递给了我们自己的观察者模式。

在Activity中使用

 
 
  1.         mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
  2.         //创建默认的线性LayoutManager
  3.         mLayoutManager = new LinearLayoutManager(this);
  4.         mRecyclerView.setLayoutManager(mLayoutManager);
  5.         //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
  6.         mRecyclerView.setHasFixedSize(true);
  7.         //创建并设置Adapter
  8.         mAdapter = new MyAdapter(data);
  9.         mRecyclerView.setAdapter(mAdapter);
  10.         mAdapter.setOnItemClickListener(new OnRecyclerViewItemClickListener(){
  11.             @Override    
  12.             public void onItemClick(View view , String data){
  13.                 Toast.makeText(MainActivity.this, data, 600).show();
  14.             }
  15.         });

完整代码

MyAdapter.java

 
 
  1. package com.example.recyclerviewdemo;
  2.  
  3. import android.support.v7.widget.RecyclerView;
  4. import android.util.Log;
  5. import android.view.LayoutInflater;
  6. import android.view.View;
  7. import android.view.ViewGroup;
  8. import android.widget.TextView;
  9.  
  10. public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{
  11.     private  String[]  datas;
  12.     public MyAdapter(String[] datas) {
  13.         this.datas = datas;
  14.     }
  15.     private OnRecyclerViewItemClickListener mOnItemClickListener = null;
  16.     
  17.     //define interface
  18.     public static interface OnRecyclerViewItemClickListener {
  19.         void onItemClick(View view , String data);
  20.     }
  21.     
  22.     @Override
  23.     public ViewHolder onCreateViewHolder(ViewGroup viewGroup,  int viewType) {
  24.         View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
  25.         ViewHolder vh = new ViewHolder(view);
  26.         //将创建的View注册点击事件
  27.         view.setOnClickListener(this);
  28.         return vh;
  29.     }
  30.     
  31.     @Override
  32.     public void onBindViewHolder(ViewHolder viewHolder,  int position) {
  33.         viewHolder.mTextView.setText(datas[position]);
  34.         //将数据保存在itemView的Tag中,以便点击时进行获取
  35.         viewHolder.itemView.setTag(datas[position]);
  36.     }
  37.  
  38.     @Override
  39.     public void onClick(View v) {
  40.         if (mOnItemClickListener != null) {
  41.             //注意这里使用getTag方法获取数据
  42.             mOnItemClickListener.onItemClick(v,(String)v.getTag());
  43.         }
  44.     }
  45.  
  46.     public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
  47.         this.mOnItemClickListener = listener;
  48.     }
  49.  
  50.     
  51.     //获取数据的数量
  52.     @Override
  53.     public int getItemCount() {
  54.         return datas.length;
  55.     }
  56.     //自定义的ViewHolder,持有每个Item的的所有界面元素
  57.     public static class ViewHolder extends RecyclerView.ViewHolder {
  58.         public TextView mTextView;
  59.         public ViewHolder(View view){
  60.         super(view);
  61.             mTextView = (TextView) view.findViewById(R.id.text);
  62.         }
  63.     }
  64. }

item.xml

 
 
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="50dip"
  5.    >
  6.     <TextView
  7.         android:id="@+id/text"
  8.         android:layout_width="wrap_content"
  9.         android:layout_height="wrap_content"
  10.         />
  11. </RelativeLayout>

MainActivity.java

 
 
  1. package com.example.recyclerviewdemo;
  2.  
  3. import com.example.recyclerviewdemo.MyAdapter.OnRecyclerViewItemClickListener;
  4.  
  5. import android.support.v7.app.ActionBarActivity;
  6. import android.support.v7.widget.LinearLayoutManager;
  7. import android.support.v7.widget.RecyclerView;
  8. import android.os.Bundle;
  9. import android.view.Menu;
  10. import android.view.MenuItem;
  11. import android.view.View;
  12. import android.widget.Toast;
  13.  
  14. public class MainActivity extends ActionBarActivity {
  15.     private RecyclerView mRecyclerView;
  16.     private LinearLayoutManager mLayoutManager;
  17.     private MyAdapter mAdapter;
  18.     private String[] data= new String[] {"aa","bb", "aa","bb", "aa","bb", "aa","bb", "aa","bb","aa","bb", "aa","bb", "aa","bb", "aa","bb", "aa","bb"  };
  19.     
  20.     @Override
  21.     protected void onCreate(Bundle savedInstanceState) {
  22.         super.onCreate(savedInstanceState);
  23.         setContentView(R.layout.activity_main);
  24.         mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
  25.         //创建默认的线性LayoutManager
  26.         mLayoutManager = new LinearLayoutManager(this);
  27.         mRecyclerView.setLayoutManager(mLayoutManager);
  28.         //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
  29.         mRecyclerView.setHasFixedSize(true);
  30.         //创建并设置Adapter
  31.         mAdapter = new MyAdapter(data);
  32.         mRecyclerView.setAdapter(mAdapter);
  33.         mAdapter.setOnItemClickListener(new OnRecyclerViewItemClickListener(){
  34.             @Override    
  35.             public void onItemClick(View view , String data){
  36.                 Toast.makeText(MainActivity.this, data, 600).show();
  37.             }
  38.         });
  39.     }
  40.  
  41.     @Override
  42.     public boolean onCreateOptionsMenu(Menu menu) {
  43.         // Inflate the menu; this adds items to the action bar if it is present.
  44.         getMenuInflater().inflate(R.menu.main, menu);
  45.         return true;
  46.     }
  47.  
  48.     @Override
  49.     public boolean onOptionsItemSelected(MenuItem item) {
  50.         // Handle action bar item clicks here. The action bar will
  51.         // automatically handle clicks on the Home/Up button, so long
  52.         // as you specify a parent activity in AndroidManifest.xml.
  53.         int id = item.getItemId();
  54.         if (id == R.id.action_settings) {
  55.             return true;
  56.         }
  57.         return super.onOptionsItemSelected(item);
  58.     }
  59.      
  60.  
  61. }

activity_main.xml

 
 
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context=".MainActivity">
  6.     <android.support.v7.widget.RecyclerView
  7.         android:id="@+id/my_recycler_view"
  8.         android:layout_width="match_parent"
  9.         android:layout_height="match_parent"
  10.         android:scrollbars="vertical"/>
  11. </RelativeLayout>

总结

在ListView中我们是调用ListView的setOnItemClickListener:

 
 
  1.         mListView.setOnItemClickListener(new OnItemClickListener() {
  2.             public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
  3.                 
  4.                     ...           
  5.                
  6.             }
  7.         });

而在我们这里是调用mAdapter的setOnItemClickListener。且回调方法public void onItemClick()的参数也不一致,ListView中有被点击item的position参数,而我们这里直接是被点击item的相关数据(这里只是一个字符串)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值