RecyclerView onClickListeners
New Example
public class SampleAdapter extends RecyclerView.Adapter<SampleAdapter.ViewHolder> {
private String[] mDataSet;
private OnRVItemClickListener mListener;
/**
* Provide a reference to the type of views that you are using (custom ViewHolder)
*/
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textView;
public ViewHolder(View v) {
super(v);
// Define click listener for the ViewHolder's View.
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { // handle click events here
Log.d(TAG, "Element " + getPosition() + " clicked.");
mListener.onRVItemClicked(getPosition(),v); //set callback
}
});
textView = (TextView) v.findViewById(R.id.textView);
}
public TextView getTextView() {
return textView;
}
}
/**
* Initialize the dataset of the Adapter.
*
* @param dataSet String[] containing the data to populate views to be used by RecyclerView.
*/
public SampleAdapter(String[] dataSet) {
mDataSet = dataSet;
}
// Create new views (invoked by the layout manager)
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
// Create a new view.
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.text_row_item, viewGroup, false);
return new ViewHolder(v);
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
// Get element from your dataset at this position and replace the contents of the view
// with that element
viewHolder.getTextView().setText(mDataSet[position]);
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mDataSet.length;
}
public void setOnRVClickListener(OnRVItemClickListener) {
mListener = OnRVItemClickListener;
}
public interface OnRVItemClickListener {
void onRVItemClicked(int position, View v);
}
}
Kotlin and RxJava example
First example reimplemented in Kotlin and using RxJava for cleaner interaction.
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.support.v7.widget.RecyclerView
import rx.subjects.PublishSubject
public class SampleAdapter(private val items: Array<String>) : RecyclerView.Adapter<SampleAdapter.ViewHolder>() {
// change to different subjects from rx.subjects to get different behavior
// BehaviorSubject for example allows to receive last event on subscribe
// PublishSubject sends events only after subscribing on the other hand which is desirable for clicks
public val itemClickStream: PublishSubject<View> = PublishSubject.create()
override fun getItemCount(): Int {
return items.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder? {
val v = LayoutInflater.from(parent.getContext()).inflate(R.layout.text_row_item, parent, false);
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
public inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val textView: TextView by lazy { view.findViewById(R.id.textView) as TextView }
init {
view.setOnClickListener { v -> itemClickStream.onNext(v) }
}
fun bind(text: String) {
textView.text = text
}
}
}
Usage is quite simple then. Itβs possible to subscribe on separate thread using RxJava facilities.
val adapter = SampleAdapter(arrayOf("Hello", "World"))
adapter.itemClickStream.subscribe { v ->
if (v.id == R.id.textView) {
// do something
}
}
Easy OnLongClick and OnClick Example
First of all, implement your view holder:
implements View.OnClickListener, View.OnLongClickListener
Then, register the listeners as follows:
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
Next, override the listeners as follows:
@Override
public void onClick(View v) {
onclicklistner.onItemClick(getAdapterPosition(), v);
}
@Override
public boolean onLongClick(View v) {
onclicklistner.onItemLongClick(getAdapterPosition(), v);
return true;
}
And finally, add the following code:
public void setOnItemClickListener(onClickListner onclicklistner) {
SampleAdapter.onclicklistner = onclicklistner;
}
public void setHeader(View v) {
this.headerView = v;
}
public interface onClickListner {
void onItemClick(int position, View v);
void onItemLongClick(int position, View v);
}
Adaptor demo
package adaptor;
import android.annotation.SuppressLint;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.wings.example.recycleview.MainActivity;
import com.wings.example.recycleview.R;
import java.util.ArrayList;
public class SampleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context context;
private ArrayList<String> arrayList;
private static onClickListner onclicklistner;
private static final int VIEW_HEADER = 0;
private static final int VIEW_NORMAL = 1;
private View headerView;
public SampleAdapter(Context context) {
this.context = context;
arrayList = MainActivity.arrayList;
}
public class HeaderViewHolder extends RecyclerView.ViewHolder {
public HeaderViewHolder(View itemView) {
super(itemView);
}
}
public class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView txt_pos;
SampleAdapter sampleAdapter;
public ItemViewHolder(View itemView, SampleAdapter sampleAdapter) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
txt_pos = (TextView) itemView.findViewById(R.id.txt_pos);
this.sampleAdapter = sampleAdapter;
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
onclicklistner.onItemClick(getAdapterPosition(), v);
}
@Override
public boolean onLongClick(View v) {
onclicklistner.onItemLongClick(getAdapterPosition(), v);
return true;
}
}
public void setOnItemClickListener(onClickListner onclicklistner) {
SampleAdapter.onclicklistner = onclicklistner;
}
public void setHeader(View v) {
this.headerView = v;
}
public interface onClickListner {
void onItemClick(int position, View v);
void onItemLongClick(int position, View v);
}
@Override
public int getItemCount() {
return arrayList.size()+1;
}
@Override
public int getItemViewType(int position) {
return position == 0 ? VIEW_HEADER : VIEW_NORMAL;
}
@SuppressLint("InflateParams")
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
if (viewType == VIEW_HEADER) {
return new HeaderViewHolder(headerView);
} else {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.custom_recycler_row_sample_item, viewGroup, false);
return new ItemViewHolder(view, this);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
if (viewHolder.getItemViewType() == VIEW_HEADER) {
return;
} else {
ItemViewHolder itemViewHolder = (ItemViewHolder) viewHolder;
itemViewHolder.txt_pos.setText(arrayList.get(position-1));
}
}
}
The example code above can be called by the following code:
sampleAdapter.setOnItemClickListener(new SampleAdapter.onClickListner() {
@Override
public void onItemClick(int position, View v) {
position = position+1;//As we are adding header
Log.e(TAG + "ON ITEM CLICK", position + "");
Snackbar.make(v, "On item click "+position, Snackbar.LENGTH_LONG).show();
}
@Override
public void onItemLongClick(int position, View v) {
position = position+1;//As we are adding header
Log.e(TAG + "ON ITEM LONG CLICK", position + "");
Snackbar.make(v, "On item longclick "+position, Snackbar.LENGTH_LONG).show();
}
});
Item Click Listeners
To implement an item click listener and/or an item long click listener, you can create an interface in your adapter:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
public interface OnItemClickListener {
void onItemSeleted(int position, View view, CustomObject object);
}
public interface OnItemLongClickListener {
boolean onItemSelected(int position, View view, CustomObject object);
}
public final class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
final int position = getAdapterPosition();
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mOnItemClickListener != null) {
mOnItemClickListener.onItemSeleted(position, view, mDataSet.get(position));
}
}
});
itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if(mOnItemLongClickListener != null) {
return mOnItemLongClickListener.onItemSelected(position, view, mDataSet.get(position));
}
}
});
}
}
private List<CustomObject> mDataSet;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
public CustomAdapter(List<CustomObject> dataSet) {
mDataSet = dataSet;
}
@Override
public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_item_custom, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) {
// Bind views
}
@Override
public int getItemCount() {
return mDataSet.size();
}
public void setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
}
public void setOnItemLongClickListener(OnItemLongClickListener listener) {
mOnItemLongClickListener = listener;
}
}
Then you can set your click listeners after you create an instance of the adapter:
customAdapter.setOnItemClickListener(new CustomAdapter.OnItemClickListener {
@Override
public void onItemSelected(int position, View view, CustomObject object) {
// Your implementation here
}
});
customAdapter.setOnItemLongClickListener(new CustomAdapter.OnItemLongClickListener {
@Override
public boolean onItemSelected(int position, View view, CustomObject object) {
// Your implementation here
return true;
}
});
Another way to implement Item Click Listener
Another way to implement item click listener is to use interface with several methods, the number of which is equal to the number of clickable views, and use overrided click listeners as you can see below. This method is more flexible, because you can set click listeners to different views and quite easy control the click logic separately for each.
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomHolder> {
private ArrayList<Object> mObjects;
private ClickInterface mClickInterface;
public interface ClickInterface {
void clickEventOne(Object obj);
void clickEventTwo(Object obj1, Object obj2);
}
public void setClickInterface(ClickInterface clickInterface) {
mClickInterface = clickInterface;
}
public CustomAdapter(){
mList = new ArrayList<>();
}
public void addItems(ArrayList<Object> objects) {
mObjects.clear();
mObjects.addAll(objects);
notifyDataSetChanged();
}
@Override
public CustomHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new CustomHolder(v);
}
@Override
public void onBindViewHolder(CustomHolder holder, int position) {
//make all even positions not clickable
holder.firstClickListener.setClickable(position%2==0);
holder.firstClickListener.setPosition(position);
holder.secondClickListener.setPosition(position);
}
private class FirstClickListener implements View.OnClickListener {
private int mPosition;
private boolean mClickable;
void setPosition(int position) {
mPosition = position;
}
void setClickable(boolean clickable) {
mPosition = position;
}
@Override
public void onClick(View v) {
if(mClickable) {
mClickInterface.clickEventOne(mObjects.get(mPosition));
}
}
}
private class SecondClickListener implements View.OnClickListener {
private int mPosition;
void setPosition(int position) {
mPosition = position;
}
@Override
public void onClick(View v) {
mClickInterface.clickEventTwo(mObjects.get(mPosition), v);
}
}
@Override
public int getItemCount() {
return mObjects.size();
}
protected class CustomHolder extends RecyclerView.ViewHolder {
FirstClickListener firstClickListener;
SecondClickListener secondClickListener;
View v1, v2;
public DialogHolder(View itemView) {
super(itemView);
v1 = itemView.findViewById(R.id.v1);
v2 = itemView.findViewById(R.id.v2);
firstClickListener = new FirstClickListener();
secondClickListener = new SecondClickListener();
v1.setOnClickListener(firstClickListener);
v2.setOnClickListener(secondClickListener);
}
}
}
And when you have an instance of adapter, you can set your click listener which listens to clicking on each of the views:
customAdapter.setClickInterface(new CustomAdapter.ClickInterface {
@Override
public void clickEventOne(Object obj) {
// Your implementation here
}
@Override
public void clickEventTwo(Object obj1, Object obj2) {
// Your implementation here
}
});
RecyclerView Click listener
public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private RecyclerTouchListener.ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final RecyclerTouchListener.ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = 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 && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
public interface ClickListener {
void onLongClick(View child, int childPosition);
void onClick(View child, int childPosition);
}
}
In MainActivity
RecyclerView recyclerView =(RecyclerView) findViewById(R.id.recyclerview);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(),recyclerView, new RecyclerTouchListener.ClickListener() {
@Override
public void onLongClick(View child, int childPosition) {
}
@Override
public void onClick(View child, int childPosition) {
}
}));