RecyclerView onClickListeners
Kotlin and RxJava example
Section titled “Kotlin and RxJava example”First example reimplemented in Kotlin and using RxJava for cleaner interaction.
import android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.support.v7.widget.RecyclerViewimport 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 }}RecyclerView Click listener
Section titled “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) {
} }));Another way to implement Item Click Listener
Section titled “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 }});New Example
Section titled “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); }}Easy OnLongClick and OnClick Example
Section titled “Easy OnLongClick and OnClick Example”First of all, implement your view holder:
implements View.OnClickListener, View.OnLongClickListenerThen, register the listeners as follows:
itemView.setOnClickListener(this);itemView.setOnLongClickListener(this);Next, override the listeners as follows:
@Overridepublic void onClick(View v) { onclicklistner.onItemClick(getAdapterPosition(), v);}
@Overridepublic 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
Section titled “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
Section titled “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; }});