recyclerViewへのクリックイベントの追加

9136 ワード

RecycleViewでは、ItemにOnItemClickなどのクリックイベントを直接開いていないので、自分でやる必要があります.クリックイベントの追加を実現するために、3つの中で比較的よく使われる方法を紹介します.
コードのダウンロード
クリックイベントをadapterに追加
比較的一般的な方法です.listViewを使用する場合、クリックイベントの追加を実現するためにこの方法を使用することもあります.adapterにクリックイベントを追加することで、最itemサブviewクリックイベントのモニタリングが可能になるからです.構想は以下の通りである:adapterで自分で定義したインタフェースタイプを新規作成し、暴露する.
private OnRecyclerViewItemClickListener mOnItenClickListener = null;
private OnRecyclerViewItemLongClickListener mOnItemLongClickListener = null;

public void setOnItemClickListener(OnRecyclerViewItemClickListener listener){
    this.mOnItenClickListener = listener;
}

public void setOnItemLongClickListener(OnRecyclerViewItemLongClickListener listener){
    this.mOnItemLongClickListener = listener;
}

指定した要素に対するクリックイベントをadapterに追加します.
v.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            if(mOnItemLongClickListener!=null)
            mOnItemLongClickListener.OnItemLongClickListener(v, (Integer) v.getTag());
            return false;
        }
    });

インタフェース呼び出しでは、自分で定義したインタフェースを呼び出して実装します.

@Override
public void onClick(View v) {
    if(mOnItemLongClickListener !=null)
    mOnItenClickListener.OnItemClickListener(v, (Integer) v.getTag());
}

Activityでインタフェースを呼び出してリスニングを実現
mMyAdapter.setOnItemClickListener(new MyAdapter.OnRecyclerViewItemClickListener() {
           @Override
           public void OnItemClickListener(View view, int position) {
               Toast.makeText(MainActivity.this,"    3       "+position,Toast.LENGTH_SHORT).show();
           }
       });
       mMyAdapter.setOnItemLongClickListener(new MyAdapter.OnRecyclerViewItemLongClickListener() {
           @Override
           public void OnItemLongClickListener(View view, int position) {
               Toast.makeText(MainActivity.this,"    3         "+position,Toast.LENGTH_SHORT).show();
           }
       });

GestureDetectorCompatの書き換えによるリスニング
RecycleViewでは対応するクリックイベントは直接実装されていませんが、提供されているapiでは、インタフェースを予約して実装していることがわかります.GestureDetectorCompatを書き換えることでitemクリックイベントのモニタリングを実現します.
 private GestureDetectorCompat gestureDetectorCompat;

    public interface OnItemClickListener{
        void onItemClick(View view, int position);
        void onItemLongClick(View view,int postion);
    }

    public ItemClickListener(final RecyclerView recyclerView,final OnItemClickListener clickListener) {
        gestureDetectorCompat = new GestureDetectorCompat(recyclerView.getContext(),
                new GestureDetector.SimpleOnGestureListener(){
                    @Override
                    public boolean onSingleTapUp(MotionEvent e) {
                        View childView = recyclerView.findChildViewUnder(e.getX(),e.getY());
                        if(childView != null && clickListener!= null){
                            clickListener.onItemClick(childView,recyclerView.getChildAdapterPosition(childView));
                        }
                        return true;
                    }

                    @Override
                    public void onLongPress(MotionEvent e) {
                        View childView = recyclerView.findChildViewUnder(e.getX(),e.getY());
                        if(childView != null && clickListener != null){
                            clickListener.onItemLongClick(childView,recyclerView.getChildAdapterPosition(childView));
                        }
                    }
                });
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        gestureDetectorCompat.onTouchEvent(e);
        return false;
    }


Activityで呼び出します.以下を参照してください.
mRecyclerView.addOnItemTouchListener(new ItemClickListener(mRecyclerView, new ItemClickListener.OnItemClickListener() {
   @Override
   public void onItemClick(View view, int position) {
       Toast.makeText(MainActivity.this, "    1       " + position, Toast.LENGTH_SHORT).show();
   }

   @Override
   public void onItemLongClick(View view, int position) {
       Toast.makeText(MainActivity.this, "    1       " + position, Toast.LENGTH_SHORT).show();
   }
}));

OnChildAttachStateChangeListenerで実現
ブログ参照http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/
package com.hut.reoger.studentsrecycleview.addClickListener;

import android.support.v7.widget.RecyclerView;
import android.view.View;

import com.hut.reoger.studentsrecycleview.R;

/**
 * Created by 24540 on 2017/3/28.
 *  Item      :   :  OnChildAttachStateChangeListener   
 *   ,    ,     item      ,       :
 *     :http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/
 */

public class ItemClickSupport {
    private final RecyclerView mRecyclerView;
    private OnItemClickListener mOnItemClickListener;
    private OnItemLongClickListener mOnItemLongClickListener;

    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mOnItemClickListener != null) {
                RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
                mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
            }
        }
    };

    private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            if (mOnItemLongClickListener != null) {
                RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
                return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
            }
            return false;
        }
    };

    private RecyclerView.OnChildAttachStateChangeListener mAttachListener
            = new RecyclerView.OnChildAttachStateChangeListener() {
        @Override
        public void onChildViewAttachedToWindow(View view) {
            if (mOnItemClickListener != null) {
                view.setOnClickListener(mOnClickListener);
            }
            if (mOnItemLongClickListener != null) {
                view.setOnLongClickListener(mOnLongClickListener);
            }
        }

        @Override
        public void onChildViewDetachedFromWindow(View view) {}
    };

    private ItemClickSupport(RecyclerView recyclerView) {
        mRecyclerView = recyclerView;
        mRecyclerView.setTag(R.id.item_click_support, this);
        mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
    }

    public static ItemClickSupport addTo(RecyclerView view) {
        ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
        if (support == null) {
            support = new ItemClickSupport(view);
        }
        return support;
    }

    public static ItemClickSupport removeFrom(RecyclerView view) {
        ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
        if (support != null) {
            support.detach(view);
        }
        return support;
    }

    public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
        mOnItemClickListener = listener;
        return this;
    }

    public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
        mOnItemLongClickListener = listener;
        return this;
    }

    private void detach(RecyclerView view) {
        view.removeOnChildAttachStateChangeListener(mAttachListener);
        view.setTag(R.id.item_click_support, null);
    }

    public interface OnItemClickListener {
        void onItemClicked(RecyclerView recyclerView, int position, View v);
    }

    public interface OnItemLongClickListener {
        boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
    }
}


MainActivityで次のように監視します.
  ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
               @Override
               public void onItemClicked(RecyclerView recyclerView, int position, View v) {
                    Toast.makeText(MainActivity.this,"    2       "+position,Toast.LENGTH_SHORT).show();
               }
           });
           ItemClickSupport.addTo(mRecyclerView).setOnItemLongClickListener(new ItemClickSupport.OnItemLongClickListener() {
               @Override
               public boolean onItemLongClicked(RecyclerView recyclerView, int position, View v) {
                   Toast.makeText(MainActivity.this,"    2         "+position,Toast.LENGTH_SHORT).show();
                   return false;
               }
           });

この方法ではitemのサブviewのモニタリングも実現できる.具体的なインプリメンテーションは、私のコードを参照してください.
以上より,3つの方法でitemクリックイベントのモニタリングを実現できる.メソッド1およびメソッド3は、itemのサブviewに対するリスニングを実現することができる.方法2は,クリック位置情報の取得を容易に実現できる.メソッド1はadapterに付加され,コードは少し結合されており,メソッド1は推奨されていない.