RecyclerView onClick
Here is a better and less tightly coupled way to implement an OnClickListener
for a RecyclerView
.
Snippet of usage:
RecyclerView recyclerView = findViewById(R.id.recycler);recyclerView.addOnItemTouchListener( new RecyclerItemClickListener(context, recyclerView ,new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View view, int position) { // do whatever } @Override public void onLongItemClick(View view, int position) { // do whatever } }));
RecyclerItemClickListener
implementation:
import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener { private OnItemClickListener mListener; public interface OnItemClickListener { public void onItemClick(View view, int position); public void onLongItemClick(View view, int position); } GestureDetector mGestureDetector; public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) { mListener = listener; mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } @Override public void onLongPress(MotionEvent e) { View child = recyclerView.findChildViewUnder(e.getX(), e.getY()); if (child != null && mListener != null) { mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child)); } } });} @Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { View childView = view.findChildViewUnder(e.getX(), e.getY()); if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) { mListener.onItemClick(childView, view.getChildAdapterPosition(childView)); return true; } return false; } @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { } @Override public void onRequestDisallowInterceptTouchEvent (boolean disallowIntercept){}}
As the API's have radically changed, It wouldn't surprise me if you were to create an OnClickListener
for each item. It isn't that much of a hassle though. In your implementation of RecyclerView.Adapter<MyViewHolder>
, you should have:
private final OnClickListener mOnClickListener = new MyOnClickListener();@Overridepublic MyViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) { View view = LayoutInflater.from(mContext).inflate(R.layout.myview, parent, false); view.setOnClickListener(mOnClickListener); return new MyViewHolder(view);}
The onClick
method:
@Overridepublic void onClick(final View view) { int itemPosition = mRecyclerView.getChildLayoutPosition(view); String item = mList.get(itemPosition); Toast.makeText(mContext, item, Toast.LENGTH_LONG).show();}
I do it in this way, without undue classes, detectors etc. Simple code inside our adapter. Especially better solution for longClick than presented before.
public class PasswordAdapter extends RecyclerView.Adapter<PasswordAdapter.ViewHolder> { private static ClickListener clickListener; public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { TextView name; public ViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(this); itemView.setOnLongClickListener(this); name = (TextView) itemView.findViewById(R.id.card_name); } @Override public void onClick(View v) { clickListener.onItemClick(getAdapterPosition(), v); } @Override public boolean onLongClick(View v) { clickListener.onItemLongClick(getAdapterPosition(), v); return false; } } public void setOnItemClickListener(ClickListener clickListener) { PasswordAdapter.clickListener = clickListener; } public interface ClickListener { void onItemClick(int position, View v); void onItemLongClick(int position, View v); }}
Then inside fragment or activity, just hit:
PasswordAdapter mAdapter = ...;mAdapter.setOnItemClickListener(new PasswordAdapter.ClickListener() { @Override public void onItemClick(int position, View v) { Log.d(TAG, "onItemClick position: " + position); } @Override public void onItemLongClick(int position, View v) { Log.d(TAG, "onItemLongClick pos = " + position); }});