为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:
- //define interface
 - public static interface OnRecyclerViewItemClickListener {
 - void onItemClick(View view , String data);
 - }
 
声明一个这个接口的变量
- private OnRecyclerViewItemClickListener mOnItemClickListener = null;
 
在onCreateViewHolder()中为每个item添加点击事件
- @Override
 - public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
 - View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
 - ViewHolder vh = new ViewHolder(view);
 - //将创建的View注册点击事件
 - view.setOnClickListener(this);
 - return vh;
 - }
 
将点击事件转移给外面的调用者:
- @Override
 - public void onClick(View v) {
 - if (mOnItemClickListener != null) {
 - //注意这里使用getTag方法获取数据
 - mOnItemClickListener.onItemClick(v,(String)v.getTag());
 - }
 - }
 
注意上面调用接口的onItemClick()中的v.getTag()方法,这需要在onBindViewHolder()方法中设置和item相关的数据
- @Override
 - public void onBindViewHolder(ViewHolder viewHolder, int position) {
 - viewHolder.mTextView.setText(datas[position]);
 - //将数据保存在itemView的Tag中,以便点击时进行获取
 - viewHolder.itemView.setTag(datas[position]);
 - }
 
最后暴露给外面的调用者,定义一个设置Listener的方法():
- public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
 - this.mOnItemClickListener = listener;
 - }
 
以上所有步骤都发生在自定义的adapter中,典型的观察者模式,有点绕的地方在于,这里涉及到两个观察者模式的使用,view的setOnClickListener本来就是观察者模式,我们将这个观察者模式的事件监听传递给了我们自己的观察者模式。
在Activity中使用
- mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
 - //创建默认的线性LayoutManager
 - mLayoutManager = new LinearLayoutManager(this);
 - mRecyclerView.setLayoutManager(mLayoutManager);
 - //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
 - mRecyclerView.setHasFixedSize(true);
 - //创建并设置Adapter
 - mAdapter = new MyAdapter(data);
 - mRecyclerView.setAdapter(mAdapter);
 - mAdapter.setOnItemClickListener(new OnRecyclerViewItemClickListener(){
 - @Override
 - public void onItemClick(View view , String data){
 - Toast.makeText(MainActivity.this, data, 600).show();
 - }
 - });
 
完整代码
MyAdapter.java
- package com.example.recyclerviewdemo;
 - import android.support.v7.widget.RecyclerView;
 - import android.util.Log;
 - import android.view.LayoutInflater;
 - import android.view.View;
 - import android.view.ViewGroup;
 - import android.widget.TextView;
 - public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener{
 - private String[] datas;
 - public MyAdapter(String[] datas) {
 - this.datas = datas;
 - }
 - private OnRecyclerViewItemClickListener mOnItemClickListener = null;
 - //define interface
 - public static interface OnRecyclerViewItemClickListener {
 - void onItemClick(View view , String data);
 - }
 - @Override
 - public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
 - View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
 - ViewHolder vh = new ViewHolder(view);
 - //将创建的View注册点击事件
 - view.setOnClickListener(this);
 - return vh;
 - }
 - @Override
 - public void onBindViewHolder(ViewHolder viewHolder, int position) {
 - viewHolder.mTextView.setText(datas[position]);
 - //将数据保存在itemView的Tag中,以便点击时进行获取
 - viewHolder.itemView.setTag(datas[position]);
 - }
 - @Override
 - public void onClick(View v) {
 - if (mOnItemClickListener != null) {
 - //注意这里使用getTag方法获取数据
 - mOnItemClickListener.onItemClick(v,(String)v.getTag());
 - }
 - }
 - public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
 - this.mOnItemClickListener = listener;
 - }
 - //获取数据的数量
 - @Override
 - public int getItemCount() {
 - return datas.length;
 - }
 - //自定义的ViewHolder,持有每个Item的的所有界面元素
 - public static class ViewHolder extends RecyclerView.ViewHolder {
 - public TextView mTextView;
 - public ViewHolder(View view){
 - super(view);
 - mTextView = (TextView) view.findViewById(R.id.text);
 - }
 - }
 - }
 
item.xml
- <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="50dip"
 - >
 - <TextView
 - android:id="@+id/text"
 - android:layout_width="wrap_content"
 - android:layout_height="wrap_content"
 - />
 - </RelativeLayout>
 
MainActivity.java
- package com.example.recyclerviewdemo;
 - import com.example.recyclerviewdemo.MyAdapter.OnRecyclerViewItemClickListener;
 - import android.support.v7.app.ActionBarActivity;
 - import android.support.v7.widget.LinearLayoutManager;
 - import android.support.v7.widget.RecyclerView;
 - import android.os.Bundle;
 - import android.view.Menu;
 - import android.view.MenuItem;
 - import android.view.View;
 - import android.widget.Toast;
 - public class MainActivity extends ActionBarActivity {
 - private RecyclerView mRecyclerView;
 - private LinearLayoutManager mLayoutManager;
 - private MyAdapter mAdapter;
 - 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" };
 - @Override
 - protected void onCreate(Bundle savedInstanceState) {
 - super.onCreate(savedInstanceState);
 - setContentView(R.layout.activity_main);
 - mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
 - //创建默认的线性LayoutManager
 - mLayoutManager = new LinearLayoutManager(this);
 - mRecyclerView.setLayoutManager(mLayoutManager);
 - //如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
 - mRecyclerView.setHasFixedSize(true);
 - //创建并设置Adapter
 - mAdapter = new MyAdapter(data);
 - mRecyclerView.setAdapter(mAdapter);
 - mAdapter.setOnItemClickListener(new OnRecyclerViewItemClickListener(){
 - @Override
 - public void onItemClick(View view , String data){
 - Toast.makeText(MainActivity.this, data, 600).show();
 - }
 - });
 - }
 - @Override
 - public boolean onCreateOptionsMenu(Menu menu) {
 - // Inflate the menu; this adds items to the action bar if it is present.
 - getMenuInflater().inflate(R.menu.main, menu);
 - return true;
 - }
 - @Override
 - public boolean onOptionsItemSelected(MenuItem item) {
 - // 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.
 - int id = item.getItemId();
 - if (id == R.id.action_settings) {
 - return true;
 - }
 - return super.onOptionsItemSelected(item);
 - }
 - }
 
activity_main.xml
- <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=".MainActivity">
 - <android.support.v7.widget.RecyclerView
 - android:id="@+id/my_recycler_view"
 - android:layout_width="match_parent"
 - android:layout_height="match_parent"
 - android:scrollbars="vertical"/>
 - </RelativeLayout>
 
总结
在ListView中我们是调用ListView的setOnItemClickListener:
- mListView.setOnItemClickListener(new OnItemClickListener() {
 - public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
 - ...
 - }
 - });
 
而在我们这里是调用mAdapter的setOnItemClickListener。且回调方法public void onItemClick()的参数也不一致,ListView中有被点击item的position参数,而我们这里直接是被点击item的相关数据(这里只是一个字符串)。
                    
                
                
            
        
浙公网安备 33010602011771号