Since you started using RecyclerView instead of ListView, you’ll find a lot to learn. The previous learning records are as follows:

Today we will learn how to implement RecyclerView Item click events. There are three ways to implement an Item click event:

  1. By RecyclerView existing method addOnItemTouchListener() to achieve

  2. Add click listener when creating ItemView

  3. When ItemView attach RecyclerView

1. ByRecyclerViewtheaddOnItemTouchListener()implementation

1.1 Viewing source Code

See RecyclerView source code can be seen,RecyclerView reserved an Item touch event method:

/**
 * Add an {@link OnItemTouchListener} to intercept touch events before they are dispatched
 * to child views or this view's standard scrolling behavior.
 *
 * 

Client code may use listeners to implement item manipulation behavior. Once a listener * returns true from * {@link OnItemTouchListener#onInterceptTouchEvent(RecyclerView, MotionEvent)} its * {@link OnItemTouchListener#onTouchEvent(RecyclerView, MotionEvent)} method will be called * for each incoming MotionEvent until the end of the gesture.

* * @param listener Listener to add * @see SimpleOnItemTouchListener */ public void addOnItemTouchListener(OnItemTouchListener listener) { mOnItemTouchListeners.add(listener); } Copy the code

We can see from the comments that this method is called before the scrolling event. You need to pass in an OnItemTouchListener object. The OnItemTouchListener code looks like this:

public static interface OnItemTouchListener { 

    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e);

    public void onTouchEvent(RecyclerView rv, MotionEvent e);

    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept);
}
Copy the code

This interface also provides an implementation class, and the official is recommended to use the implementation class SimpleOnItemTouchListener

/**
 * An implementation of {@link RecyclerView.OnItemTouchListener} that has empty method bodies and
 * default return values.
 * 

<

p>
 * You may prefer to extend this class if you don't need to override all methods. Another
 * benefit of using this class is future compatibility. As the interface may change, we'll
 * always provide a default implementation on this class so that your code won't break when
 * you update to a new version of the support library.
 */
public static class SimpleOnItemTouchListener implements RecyclerView.OnItemTouchListener {
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
    }
}
Copy the code

In the touch interface, a MotionEvent object is called back when touched, parsing the user’s actions using GestureDetectorCompat.

1.2 Implement click event monitoring

Write a ItemClickListener class inheritance SimpleOnItemTouchListener, construct the incoming RecyclerView object and click on the Item the callback, and overwrite the superclass Boolean OnInterceptTouchEvent (RecyclerView RV, MotionEvent E);

/** * Created by DevWiki on 2016/7/16. */ Public Class ItemClickListener extends RecyclerView.SimpleOnItemTouchListener { private OnItemClickListener clickListener; private GestureDetectorCompat gestureDetector; public interface OnItemClickListener { void onItemClick(View view, int position); void onItemLongClick(View view, int position); } public ItemClickListener(final RecyclerView recyclerView, OnItemClickListener listener) { this.clickListener = listener; gestureDetector = 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 && gestureDetector.onTouchEvent(e)) { 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) { gestureDetector.onTouchEvent(e); return false; }}Copy the code

In the GestureDetectorCompat gesture callback we override:

  1. Boolean onSingleTapUp(MotionEvent e) Click to lift the callback

  2. Void onLongPress(MotionEvent E) Long press to call back

1.3 Using Event Listening

Add the addOnItemTouchListener() method to the RecyclerView object and then handle the events you need in the callback:

recyclerView.addOnItemTouchListener(new SingleItemClickListener(recyclerView, new SingleItemClickListener.OnItemClickListener() { @Override public void onItemClick(View view, int position) { DevLog.i("touch click name:" + position); Toast.makeText(SingleActivity.this, "touch click:" + position, Toast.LENGTH_SHORT).show(); } @Override public void onItemLongClick(View view, int position) { DevLog.i("touch long click:" + position); Toast.makeText(SingleActivity.this, "touch long click:" + position, Toast.LENGTH_SHORT).show(); }}));Copy the code

2. To createItemViewAdd click listening when

This method, like the ListView method, adds a click event to the View created in the Adapter. Such as:

@Override public void bindCustomViewHolder(SingleHolder holder, final int position) { Person person = getItem(position);  holder.nameView.setText(person.getName()); holder.ageView.setText(String.valueOf(person.getAge())); if (clickListener ! = null) { holder.nameView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickListener.onNameClick(position); }}); holder.ageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { clickListener.onAgeClick(position); }}); }}Copy the code

Then add the listening callback to the Adapter object:

singleAdapter.setClickListener(new SingleAdapter.OnSingleItemClickListener() { @Override public void onNameClick(int position) { DevLog.i("adapter click name:" + position); Toast.makeText(SingleActivity.this, "adapter click name:" + position, Toast.LENGTH_SHORT).show(); } @Override public void onAgeClick(int position) { DevLog.i("adapter click age:" + position); Toast.makeText(SingleActivity.this, "adapter click name:" + position, Toast.LENGTH_SHORT).show(); }});Copy the code

3. WhenItemView attach RecyclerViewWhen implementing

Get Your Clicks on RecyclerView Get Your clicks on RecyclerView Get Your clicks on RecyclerView

The code is as follows:

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);  }}Copy the code

The code above to set up a OnChildAttachStateChangeListener RecyclerView event listeners, when View the attach RecyclerView set up event listeners.

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) {} };Copy the code

4. Compare the three ways

The above three ways are:

  1. By RecyclerView existing method addOnItemTouchListener() to achieve

  2. Add click listener when creating ItemView

  3. When ItemView attach RecyclerView

From the realization process of the above three ways, we can know:

  1. All three can realize the monitoring of click events and long press events of ItemView.

  2. The first method makes it easy to get the coordinates the user clicked.

  3. The second and third methods are very convenient for listening on child Views in an ItemView.

  4. The first method and the third method can be written in separate classes, making the code separate and cleaner than the second method written in Adapter

To sum up:

If all you want to do is listenItemViewClick event or long press event, three ways can be.

If you want to listen inItemViewEach child in theViewClick events, using the second or third comparison aspect.

5. Afterword.

The above three ways are learned in the RecyclerView process, the project address is as follows: dev-wiki /RecyclerView

If there is any error please correct, if you have a better way to achieve, please leave a message or contact me, thank you!

You can also follow my public account to get the latest articles: