爲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的相關數據(這裏只是一個字符串)。


發佈了24 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章