Warum hat RecyclerView onItemClickListener () nicht?

Ich habe RecyclerView erkundet und war überrascht zu sehen, dass RecyclerView nicht onItemClickListener() . Weil RecyclerView sich RecyclerView

android.view.ViewGruppe

und ListView erweitert

android.widget.AbsListView

. Wie auch immer, ich habe mein Problem getriggers, indem ich onClick in meinem RecyclerView.Adapter :

 public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener { public TextView txtViewTitle; public ImageView imgViewIcon; public ViewHolder(View itemLayoutView) { super(itemLayoutView); txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title); imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon); } @Override public void onClick(View v) { } } 

onItemClickListener() möchte ich wissen, warum Google onItemClickListener() ?

Gibt es ein performancesproblem oder etwas anderes?

tl; dr 2016 Verwenden Sie RxJava und ein PublishSubject, um ein Observable für die Klicks verfügbar zu machen.

 public class ReactiveAdapter extends RecyclerView.Adapter { String[] mDataset = { "Data", "In", "Adapter" }; private final PublishSubject onClickSubject = PublishSubject.create(); @Override public void onBindViewHolder(final ViewHolder holder, int position) { final String element = mDataset[position]; holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onClickSubject.onNext(element); } }); } public Observable getPositionClicks(){ return onClickSubject.asObservable(); } } 

Original Beitrag:

Seit der Einführung von ListView ist onItemClickListener problematisch. In dem Moment, in dem Sie einen Klick-Listener für eines der internen Elemente haben, würde der Callback nicht ausgetriggers werden, aber es wurde nicht gemeldet oder gut dokumentiert (wenn überhaupt), also gab es eine Menge Verwirrung und SO-Fragen dazu.

Da RecyclerView einen Schritt weiter geht und kein Konzept für eine Zeile / Spalte hat, sondern eine willkürlich festgelegte Menge an untergeordneten Elementen, haben sie das onClick an jede einzelne oder an die Implementierung des Programmierers delegiert.

Denken Sie an Recyclerview nicht als ListView 1: 1 Ersatz, sondern eher als flexiblere Komponente für komplexe Anwendungsfälle. Und wie Sie sagen, ist Ihre Lösung, was Google von Ihnen erwartet hat. Jetzt haben Sie einen Adapter, der onClick an eine Schnittstelle delegieren kann, die an den Konstruktor übergeben wurde. ListView ist das richtige Muster für ListView und Recyclerview .

 public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener { public TextView txtViewTitle; public ImageView imgViewIcon; public IMyViewHolderClicks mListener; public ViewHolder(View itemLayoutView, IMyViewHolderClicks listener) { super(itemLayoutView); mListener = listener; txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title); imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon); imgViewIcon.setOnClickListener(this); itemLayoutView.setOnClickListener(this); } @Override public void onClick(View v) { if (v instanceof ImageView){ mListener.onTomato((ImageView)v); } else { mListener.onPotato(v); } } public static interface IMyViewHolderClicks { public void onPotato(View caller); public void onTomato(ImageView callerImage); } } 

und dann auf deinem Adapter

 public class MyAdapter extends RecyclerView.Adapter { String[] mDataset = { "Data" }; @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_layout, parent, false); MyAdapter.ViewHolder vh = new ViewHolder(v, new MyAdapter.ViewHolder.IMyViewHolderClicks() { public void onPotato(View caller) { Log.d("VEGETABLES", "Poh-tah-tos"); }; public void onTomato(ImageView callerImage) { Log.d("VEGETABLES", "To-m8-tohs"); } }); return vh; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder holder, int position) { // Get element from your dataset at this position // Replace the contents of the view with that element // Clear the ones that won't be used holder.txtViewTitle.setText(mDataset[position]); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return mDataset.length; } ... 

Sehen Sie sich nun den letzten Code an: onCreateViewHolder(ViewGroup parent, int viewType) die Signatur schlägt bereits verschiedene Ansichtsarten vor. Für jeden von ihnen benötigen Sie auch einen anderen Ansichtshalter, und anschließend kann jeder von ihnen einen anderen Satz von Klicks haben. Oder Sie können einfach einen generischen Viewholder erstellen, der eine View und einen onClickListener und entsprechend onClickListener . Oder eine Ebene an den Orchestrator delegieren, sodass mehrere Fragmente / Aktivitäten dieselbe Liste mit unterschiedlichem Klickverhalten aufweisen. Auch hier ist jede Flexibilität auf Ihrer Seite.

Es ist eine wirklich benötigte Komponente und entspricht ziemlich genau unseren internen Implementierungen und Verbesserungen von ListView . Es ist gut, dass Google es endlich anerkennt.

Eine alternative Lösung ist die von Hugo Visser vorgeschlagene Android GDE. Er stellte eine lizenzfreie class zur Verfügung, damit Sie Ihren Code einfach eingeben und verwenden können.

Verwendung:

 ItemClickSupport.addTo(mRecyclerView) .setOnItemClickListener(new ItemClickSupport.OnItemClickListener() { @Override public void onItemClicked(RecyclerView recyclerView, int position, View v) { // do it } }); 

(es unterstützt auch lange Artikel klicken)

Implementierung (Kommentare von mir hinzugefügt):

 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) { // ask the RecyclerView for the viewHolder of this view. // then use it to get the position for the adapter 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) { // every time a new child view is attached add click listeners to it if (mOnItemClickListener != null) { view.setOnClickListener(mOnClickListener); } if (mOnItemLongClickListener != null) { view.setOnLongClickListener(mOnLongClickListener); } } @Override public void onChildViewDetachedFromWindow(View view) { } }; private ItemClickSupport(RecyclerView recyclerView) { mRecyclerView = recyclerView; // the ID must be declared in XML, used to avoid // replacing the ItemClickSupport without removing // the old one from the RecyclerView mRecyclerView.setTag(R.id.item_click_support, this); mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener); } public static ItemClickSupport addTo(RecyclerView view) { // if there's already an ItemClickSupport attached // to this RecyclerView do not replace it, use it 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); } } 

Erstellen Sie auch eine Datei values/ids.xml und values/ids.xml diese ein:

 < ?xml version="1.0" encoding="utf-8"?>    

Diese class funktioniert, indem ein RecyclerView.OnChildAttachStateChangeListener an die RecyclerView . Dieser Listener wird jedes Mal benachrichtigt, wenn ein Kind mit dem RecyclerView verbunden oder von ihm getrennt wird. Der Code verwendet dies, um einen Tap / Long Click-Listener an die Ansicht anzuhängen. Dieser Listener fragt den RecyclerView nach dem RecyclerView.ViewHolder der die Position enthält.

Sie können den Code auch anpassen, um Ihnen den Halter selbst zurückzugeben, wenn Sie mehr benötigen.

Denken Sie daran, dass es völlig in Ordnung ist, es in Ihrem Adapter zu handhaben, indem Sie auf jede Ansicht Ihrer Liste einen Klick-Listener setzen, wie andere vorgeschlagene Antworten. Es ist einfach nicht die effizienteste Methode (Sie erstellen jedes Mal einen neuen Listener, wenn Sie eine Ansicht wiederverwenden), aber es funktioniert und in den meisten Fällen ist dies kein Problem.

Über das Warum RecyclerView hat keinen onItemClickListener .

Der RecyclerView ist eine Toolbox, im Gegensatz zum alten ListView hat er weniger Features und mehr Flexibilität. Der onItemClickListener ist nicht das einzige Feature, das aus ListView entfernt wird. Aber es hat viele Zuhörer und Methoden, um es nach Ihren Wünschen zu erweitern, es ist viel mächtiger in den richtigen Händen;).

Meiner Meinung nach ist das Fast-Scroll- Feature das komplexeste in RecyclerView entfernte Feature. Die meisten anderen functionen können einfach erneut implementiert werden.

Ich mag diesen Weg und ich benutze ihn

Innerhalb

 public Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 

Stellen

 View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_image_and_text, parent, false); v.setOnClickListener(new MyOnClickListener()); 

Und erstellen Sie diese class überall dort, wo Sie es wollen

 class MyOnClickListener implements View.OnClickListener { @Override public void onClick(View v) { int itemPosition = recyclerView.indexOfChild(v); Log.e("Clicked and Position is ",String.valueOf(itemPosition)); } } 

Ich habe vorher gelesen, dass es einen besseren Weg gibt, aber ich mag diesen Weg ist einfach und nicht kompliziert.

Android Recyclerview Mit onItemClickListener , warum wir nicht versuchen können, funktioniert ListView nur wie ListView .

Quelle: Link

 public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener { private OnItemClickListener mListener; public interface OnItemClickListener { public void onItemClick(View view, int position); } GestureDetector mGestureDetector; public RecyclerItemClickListener(Context context, OnItemClickListener listener) { mListener = listener; mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } }); } @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 false; } @Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } } 

Und setzen Sie dies auf RecyclerView:

  recyclerView = (RecyclerView)rootView. findViewById(R.id.recyclerView); RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(mLayoutManager); recyclerView.addOnItemTouchListener( new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View view, int position) { // TODO Handle item click Log.e("@@@@@",""+position); } }) ); 

Jungs verwenden diesen Code in Ihrer Haupttätigkeit. Sehr effiziente Methode

 RecyclerView recyclerView = (RecyclerView) findViewById(R.id.users_list); UsersAdapter adapter = new UsersAdapter(users, this); recyclerView.setAdapter(adapter); adapter.setOnCardClickListner(this); 

Hier ist Ihre Adapterklasse.

 public class UsersAdapter extends RecyclerView.Adapter { private ArrayList mDataSet; OnCardClickListner onCardClickListner; public UsersAdapter(ArrayList mDataSet) { this.mDataSet = mDataSet; } @Override public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_row_layout, parent, false); UserViewHolder userViewHolder = new UserViewHolder(v); return userViewHolder; } @Override public void onBindViewHolder(UserViewHolder holder, final int position) { holder.name_entry.setText(mDataSet.get(position).getUser_name()); holder.cardView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onCardClickListner.OnCardClicked(v, position); } }); } @Override public int getItemCount() { return mDataSet.size(); } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); } public static class UserViewHolder extends RecyclerView.ViewHolder { CardView cardView; TextView name_entry; public UserViewHolder(View itemView) { super(itemView); cardView = (CardView) itemView.findViewById(R.id.user_layout); name_entry = (TextView) itemView.findViewById(R.id.name_entry); } } public interface OnCardClickListner { void OnCardClicked(View view, int position); } public void setOnCardClickListner(OnCardClickListner onCardClickListner) { this.onCardClickListner = onCardClickListner; } } 

Danach erhalten Sie diese Überschreibungsmethode in Ihrer Aktivität.

 @Override public void OnCardClicked(View view, int position) { Log.d("OnClick", "Card Position" + position); } 

Dank @marmor habe ich meine Antwort aktualisiert.

Ich denke, es ist eine gute Lösung, onClick () im ViewHolder- classnkonstruktor zu behandeln und über die OnItemClickListener- Schnittstelle an die Elternklasse weiterzugeben .

MyAdapter.java

 public class MyAdapter extends RecyclerView.Adapter{ private LayoutInflater layoutInflater; private List items; private AdapterView.OnItemClickListener onItemClickListener; public MyAdapter(Context context, AdapterView.OnItemClickListener onItemClickListener, List items) { layoutInflater = LayoutInflater.from(context); this.items = items; this.onItemClickListener = onItemClickListener; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = layoutInflater.inflate(R.layout.my_row_layout, parent, false); return new ViewHolder(view); } @Override public void onBindViewHolder(ViewHolder holder, int position) { MyObject item = items.get(position); } public MyObject getItem(int position) { return items.get(position); } class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { private TextView title; private ImageView avatar; public ViewHolder(View itemView) { super(itemView); title = itemView.findViewById(R.id.title); avatar = itemView.findViewById(R.id.avatar); title.setOnClickListener(this); avatar.setOnClickListener(this); itemView.setOnClickListener(this); } @Override public void onClick(View view) { //passing the clicked position to the parent class onItemClickListener.onItemClick(null, view, getAdapterPosition(), view.getId()); } } } 

Verwendung von Adaptern in anderen classn:

MyFragment.java

 public class MyFragment extends Fragment implements AdapterView.OnItemClickListener { private RecyclerView recycleview; private MyAdapter adapter; . . . private void init(Context context) { //passing this fragment as OnItemClickListener to the adapter adapter = new MyAdapter(context, this, items); recycleview.setAdapter(adapter); } @Override public void onItemClick(AdapterView< ?> parent, View view, int position, long id) { //you can get the clicked item from the adapter using its position MyObject item = adapter.getItem(position); //you can also find out which view was clicked switch (view.getId()) { case R.id.title: //title view was clicked break; case R.id.avatar: //avatar view was clicked break; default: //the whole row was clicked } } } 

> Wie unterscheidet sich RecyclerView von Listview?

Ein Unterschied besteht darin, dass es eine LayoutManager class mit RecyclerView gibt, mit der Sie Ihr RecyclerView Like-

Horizontales oder vertikales Scrollen durch LinearLayoutManager

GridLayout von GridLayoutManager

Staggered GridLayout von StaggeredGridLayoutManager

Wie beim horizontalen Scrollen für RecyclerView-

 LinearLayoutManager llm = new LinearLayoutManager(context); llm.setOrientation(LinearLayoutManager.HORIZONTAL); recyclerView.setLayoutManager(llm); 

Wie man alles zusammensetzt Beispiel …

  • onClick () Handhabung
  • Cursor – RecyclerView
  • ViewHolder-Typen

     public class OrderListCursorAdapter extends CursorRecyclerViewAdapter { private static final String TAG = OrderListCursorAdapter.class.getSimpleName(); private static final int ID_VIEW_HOLDER_ACTUAL = 0; private static final int ID_VIEW_HOLDER = 1; public OrderListCursorAdapter(Context context, Cursor cursor) { super(context, cursor); } public static class ViewHolderActual extends ViewHolder { private static final String TAG = ViewHolderActual.class.getSimpleName(); protected IViewHolderClick listener; protected Button button; public ViewHolderActual(View v, IViewHolderClick listener) { super(v, listener); this.listener = listener; button = (Button) v.findViewById(R.id.orderList_item_button); button.setOnClickListener(this); } public void initFromData(OrderData data) { Log.d(TAG, ">>onCreateViewHolder(parent=" + parent + ", viewType=" + viewType + ")"); ViewHolder result; switch (viewType) { case ID_VIEW_HOLDER_ACTUAL: { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_layout_actual, parent, false); result = new ViewHolderActual(itemView, new ViewHolderActual.IViewHolderClick() { @Override public void onCardClick(View view, int position, ViewHolder viewHolder) { Log.d(TAG, "> 

Soweit ich das verstanden habe, kann MLprogrammer-CiM einfach antworten, einfach:

 class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ private ImageView image; private TextView title; private TextView price; public MyViewHolder(View itemView) { super(itemView); image = (ImageView)itemView.findViewById(R.id.horizontal_list_image); title = (TextView)itemView.findViewById(R.id.horizontal_list_title); price = (TextView)itemView.findViewById(R.id.horizontal_list_price); image.setOnClickListener(this); title.setOnClickListener(this); price.setOnClickListener(this); } @Override public void onClick(View v) { Toast.makeText(context, "Item click nr: "+getLayoutPosition(), Toast.LENGTH_SHORT).show(); } } 

Nach dem Lesen von @ MLProgrammer-CiM ‘s Antwort, hier ist mein Code:

 class NormalViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ @Bind(R.id.card_item_normal) CardView cardView; public NormalViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); cardView.setOnClickListener(this); } @Override public void onClick(View v) { if(v instanceof CardView) { // use getAdapterPosition() instead of getLayoutPosition() int itemPosition = getAdapterPosition(); removeItem(itemPosition); } } } 

Im Anschluss an die hervorragende RxJava-Lösung von MLProgrammer-CiM

Klicks konsumieren / beobachten

 ReactiveAdapter rxAdapter = new ReactiveAdapter(); rxAdapter.getPositionClicks().subscribe(mClickConsumer); Consumer mClickConsumer = new Consumer() { @Override public void accept(@NonNull String element) throws Exception { Toast.makeText(getApplicationContext(), element +" was clicked", Toast.LENGTH_LONG).show(); } }; 

RxJava 2. +

Modifizieren Sie das ursprüngliche tl; dr als:

 public Observable getPositionClicks(){ return onClickSubject; } 

PublishSubject#asObservable() wurde entfernt. PublishSubject einfach das PublishSubject das ein Observable .

Ich habe es so gemacht, es ist sehr einfach:

Fügen Sie einfach eine Linie für Clicked RecyclerView Position hinzu :

 int position = getLayoutPosition() 

Vollständiger Code für die ViewHolder- class:

 private class ChildViewHolder extends RecyclerView.ViewHolder { public ImageView imageView; public TextView txtView; public ChildViewHolder(View itemView) { super(itemView); imageView= (ImageView)itemView.findViewById(R.id.imageView); txtView= (TextView) itemView.findViewById(R.id.txtView); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Log.i("RecyclerView Item Click Position", String.valueOf(getLayoutPosition())); } }); } } 

Hoffe das wird dir helfen.

Ich verwende diese Methode, um eine Absicht von RecyclerView zu starten:

 @Override public void onBindViewHolder(ViewHolder viewHolder, int i) { final MyClass myClass = mList.get(i); viewHolder.txtViewTitle.setText(myclass.name); ... viewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v){ Intent detailIntent = new Intent(mContext, type.class); detailIntent.putExtra("MyClass", myclass); mContext.startActivity(detailIntent); } } ); 

Hier ist ein Weg, um es recht einfach zu implementieren, wenn Sie eine Liste von POJOs haben und eines von außerhalb des Adapters abrufen möchten.

Erstellen Sie in Ihrem Adapter einen Listener für die click-Ereignisse und eine Methode, um sie festzulegen:

 public class MyAdapter extends RecyclerView.Adapter { ... private List mMyPojos; private static OnItemClickListener mOnItemClickListener; ... public interface OnItemClickListener { public void onItemClick(MyPojo pojo); } ... public void setOnItemClickListener(OnItemClickListener onItemClickListener){ mOnItemClickListener = onItemClickListener; } ... 

}

Implementieren Sie in Ihrem ViewHolder onClickListener und erstellen Sie ein classnmitglied, um das POJO, das die Ansicht präsentiert, vorübergehend zu speichern (in diesem Beispiel wäre die Erstellung eines Setter besser):

 public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public MyPojo mCurrentPojo; ... public ViewHolder(View view) { super(v); ... view.setOnClickListener(this); //You could set this on part of the layout too } ... @Override public void onClick(View view) { if(mOnItemClickListener != null && mCurrentPojo != null){ mOnItemClickListener.onItemClick(mCurrentPojo); } } 

Setzen Sie in Ihrem Adapter den aktuellen POJO zurück, wenn der ViewHolder gebunden ist (oder auf null, wenn die aktuelle Ansicht keinen enthält):

 @Override public void onBindViewHolder(final ViewHolder holder, final int position) { final MyPojo currentPojo = mMyPojos.get(position); holder.mCurrentPojo = currentPojo; ... 

That’s it, now you can use it like this from your fragment/activity:

  mMyAdapter.setOnItemClickListener(new mMyAdapter.OnItemClickListener() { @Override public void onItemClick(MyPojo pojo) { //Do whatever you want with your pojo here } }); 

See my approach on this:

First declare an interface like this:

 /** * Interface used for delegating item click events in a {@link android.support.v7.widget.RecyclerView} * Created by Alex on 11/28/2015. */ public interface OnRecyclerItemClickListener { /** * Called when a click occurred inside a recyclerView item view * @param view that was clicked * @param position of the clicked view * @param item the concrete data that is displayed through the clicked view */ void onItemClick(View view, int position, T item); } 

Then create the adapter:

 public class CustomRecyclerAdapter extends RecyclerView.Adapter { private class InternalClickListener implements View.OnClickListener{ @Override public void onClick(View v) { if(mRecyclerView != null && mItemClickListener != null){ // find the position of the item that was clicked int position = mRecyclerView.getChildAdapterPosition(v); Data data = getItem(position); // notify the main listener mItemClickListener.onItemClick(v, position, data); } } } private final OnRecyclerItemClickListener mItemClickListener; private RecyclerView mRecyclerView; private InternalClickListener mInternalClickListener; /** * * @param itemClickListener used to trigger an item click event */ public PlayerListRecyclerAdapter(OnRecyclerItemClickListener itemClickListener){ mItemClickListener = itemClickListener; mInternalClickListener = new InternalClickListener(); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false); v.setOnClickListener(mInternalClickListener); ViewHolder viewHolder = new ViewHolder(v); return viewHolder; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { // do your binding here } @Override public int getItemCount() { return mDataSet.size(); } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); mRecyclerView = recyclerView; } @Override public void onDetachedFromRecyclerView(RecyclerView recyclerView) { super.onDetachedFromRecyclerView(recyclerView); mRecyclerView = null; } public Data getItem(int position){ return mDataset.get(position); } } 

And now let’s see how to integrate this from a fragment:

 public class TestFragment extends Fragment implements OnRecyclerItemClickListener{ private RecyclerView mRecyclerView; @Override public void onItemClick(View view, int position, Data item) { // do something } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.test_fragment, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { mRecyclerView = view.findViewById(idOfTheRecycler); mRecyclerView .setAdapter(new CustomRecyclerAdapter(this)); } 

If you want to add onClick() to the child view of items, for example, a button in item, I found that you can do it easily in onCreateViewHolder() of your own RecyclerView.Adapter just like this:

  @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater .from(parent.getContext()) .inflate(R.layout.cell, null); Button btn = (Button) v.findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //do it } }); return new MyViewHolder(v); } 

i don’t know whether it’s a good way, but it works well. If anyone has a better idea, very glad to tell me and correct my answer! 🙂

Yes you can

 public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) { //inflate the view View view = LayoutInflator.from(parent.getContext()).inflate(R.layout.layoutID,null); ViewHolder holder = new ViewHolder(view); //here we can set onClicklistener view.setOnClickListener(new View.OnClickListeener(){ public void onClick(View v) { //action } }); return holder; 

Here you can handle multiple onclick see below code and it is very efficient

  public class RVNewsAdapter extends RecyclerView.Adapter { private Context context; List newsList; // Allows to remember the last item shown on screen private int lastPosition = -1; public RVNewsAdapter(List newsList, Context context) { this.newsList = newsList; this.context = context; } public static class FeedHolder extends RecyclerView.ViewHolder implements OnClickListener { ImageView img_main; TextView tv_title; Button bt_facebook, bt_twitter, bt_share, bt_comment; public FeedHolder(View itemView) { super(itemView); img_main = (ImageView) itemView.findViewById(R.id.img_main); tv_title = (TextView) itemView.findViewById(R.id.tv_title); bt_facebook = (Button) itemView.findViewById(R.id.bt_facebook); bt_twitter = (Button) itemView.findViewById(R.id.bt_twitter); bt_share = (Button) itemView.findViewById(R.id.bt_share); bt_comment = (Button) itemView.findViewById(R.id.bt_comment); img_main.setOnClickListener(this); bt_facebook.setOnClickListener(this); bt_twitter.setOnClickListener(this); bt_comment.setOnClickListener(this); bt_share.setOnClickListener(this); } @Override public void onClick(View v) { if (v.getId() == bt_comment.getId()) { Toast.makeText(v.getContext(), "Comment " , Toast.LENGTH_SHORT).show(); } else if (v.getId() == bt_facebook.getId()) { Toast.makeText(v.getContext(), "Facebook " , Toast.LENGTH_SHORT).show(); } else if (v.getId() == bt_twitter.getId()) { Toast.makeText(v.getContext(), "Twitter " , Toast.LENGTH_SHORT).show(); } else if (v.getId() == bt_share.getId()) { Toast.makeText(v.getContext(), "share " , Toast.LENGTH_SHORT).show(); } else { Toast.makeText(v.getContext(), "ROW PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show(); } } } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); } @Override public FeedHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.feed_row, parent, false); FeedHolder feedHolder = new FeedHolder(view); return feedHolder; } @Override public void onBindViewHolder(FeedHolder holder, int position) { holder.tv_title.setText(newsList.get(position).getTitle()); // Here you apply the animation when the view is bound setAnimation(holder.img_main, position); } @Override public int getItemCount() { return newsList.size(); } /** * Here is the key method to apply the animation */ private void setAnimation(View viewToAnimate, int position) { // If the bound view wasn't previously displayed on screen, it's animated if (position > lastPosition) { Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left); viewToAnimate.startAnimation(animation); lastPosition = position; } } } 

Modified my comment…

 public class MyViewHolder extends RecyclerView.ViewHolder { private Context mContext; public MyViewHolder(View itemView) { super(itemView); mContext = itemView.getContext(); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int itemPosition = getLayoutPosition(); Toast.makeText(mContext, "" + itemPosition, Toast.LENGTH_SHORT).show(); } }); } 

Check this one in which I have implemented all the things with a proper way

RecyclerViewHolder Class

 public class RecyclerViewHolder extends RecyclerView.ViewHolder { //view holder is for girdview as we used in the listView public ImageView imageView,imageView2; public RecyclerViewHolder(View itemView) { super(itemView); this.imageView=(ImageView)itemView.findViewById(R.id.image); } } 

Adapter

 public class RecyclerView_Adapter extends RecyclerView.Adapter { //RecyclerView will extend to recayclerview Adapter private ArrayList arrayList; private Context context; private static RecyclerViewClickListener itemListener; //constructor of the RecyclerView Adapter RecyclerView_Adapter(Context context,ArrayList arrayList,RecyclerViewClickListener itemListener){ this.context=context; this.arrayList=arrayList; this.itemListener=itemListener; } @Override public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //this method will inflate the custom layout and return as viewHolder LayoutInflater layoutInflater=LayoutInflater.from(parent.getContext()); ViewGroup mainGroup=(ViewGroup) layoutInflater.inflate(R.layout.single_item,parent,false); RecyclerViewHolder listHolder=new RecyclerViewHolder(mainGroup); return listHolder; } @Override public void onBindViewHolder(RecyclerViewHolder holder, final int position) { final ModelClass modelClass=arrayList.get(position); //holder RecyclerViewHolder mainHolder=(RecyclerViewHolder)holder; //convert the drawable image into bitmap Bitmap image= BitmapFactory.decodeResource(context.getResources(),modelClass.getImage()); //set the image into imageView mainHolder.imageView.setImageBitmap(image); //to handle on click event when clicked on the recyclerview item and // get it through the RecyclerViewHolder class we have defined the views there mainHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //get the position of the image which is clicked itemListener.recyclerViewListClicked(v,position); } }); } @Override public int getItemCount() { return (null!=arrayList?arrayList.size():0); } } 

The interface

 public interface RecyclerViewClickListener { //this is method to handle the event when clicked on the image in Recyclerview public void recyclerViewListClicked(View v,int position); } //and to call this method in activity RecyclerView_Adapter adapter=new RecyclerView_Adapter(Wallpaper.this,arrayList,this); recyclerView.setAdapter(adapter); adapter.notifyDataSetChanged(); @Override public void recyclerViewListClicked(View v,int position){ imageView.setImageResource(wallpaperImages[position]); } 

Das hat für mich funktioniert:

 @Override public void onBindViewHolder(PlacesListViewAdapter.ViewHolder holder, int position) { ---- ---- ---- // Set setOnClickListener(holder); } @Override public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { ---- ---- ---- @Override public void onClick(View view) { // Use to get the item clicked getAdapterPosition() } } 

Access the mainView of rowLayout(cell) for you RecyclerView and in your OnBindViewHolder write this code:

  @Override public void onBindViewHolder(MyViewHolder holder, final int position) { Movie movie = moviesList.get(position); holder.mainView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { System.out.println("pos " + position); } }); } 

es hat für mich funktioniert. Hoffe es wird helfen. Most simplest way.

Inside View Holder

 class GeneralViewHolder extends RecyclerView.ViewHolder { View cachedView = null; public GeneralViewHolder(View itemView) { super(itemView); cachedView = itemView; } 

Inside OnBindViewHolder()

 @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) { final GeneralViewHolder generalViewHolder = (GeneralViewHolder) holder; generalViewHolder.cachedView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(context, "item Clicked at "+position, Toast.LENGTH_SHORT).show(); } }); 

And let me know, do you have any question about this solution ?

  main_recyclerview.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() { @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { int position=rv.getChildAdapterPosition(rv.findChildViewUnder(e.getX(),e.getY())); switch (position) { case 0: { wifi(position); adapter2.notifyDataSetChanged(); } break; case 1: { sound(position); adapter2.notifyDataSetChanged(); } break; case 2: { bluetooth(position); adapter2.notifyDataSetChanged(); } break; } return true; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { } }); 

RecyclerView doesn’t have an onItemClickListener because RecyclerView is responsible for recycling views (surprise!), so it’s the responsibility of the view that is recycled to handle the click events it receives.

This actually makes it much easier to use, especially if you had items that can be clicked in multiple places.


Anyways, detecting click on a RecyclerView item is very easy. All you need to do is define an interface (if you’re not using Kotlin, in which case you just pass in a lambda):

 public class MyAdapter extends RecyclerView.Adapter { private final Clicks clicks; public MyAdapter(Clicks clicks) { this.clicks = clicks; } private List items = Collections.emptyList(); public void updateData(List items) { this.items = items; notifyDataSetChanged(); // TODO: use ListAdapter for diffing instead if you need animations } public interface Clicks { void onItemSelected(MyObject myObject, int position); } public class MyViewHolder extends RecyclerView.ViewHolder { private MyObject myObject; public MyViewHolder(View view) { super(view); // bind views view.setOnClickListener((v) -> { int adapterPosition = getAdapterPosition(); if(adapterPosition >= 0) { clicks.onItemSelected(myObject, adapterPosition); } }); } public void bind(MyObject myObject) { this.myObject = myObject; // bind data to views } } } 

Same code in Kotlin:

 class MyAdapter(val itemClicks: (MyObject, Int) -> Unit): RecyclerView.Adapter() { private var items: List = Collections.emptyList() fun updateData(items: List) { this.items = items notifyDataSetChanged() // TODO: use ListAdapter for diffing instead if you need animations } inner class MyViewHolder(val myView: View): RecyclerView.ViewHolder(myView) { private lateinit var myObject: MyObject init { // binds views myView.onClick { val adapterPosition = getAdapterPosition() if(adapterPosition >= 0) { itemClicks.invoke(myObject, adapterPosition) } } } fun bind(myObject: MyObject) { this.myObject = myObject // bind data to views } } } 

Instead of implementing interface View.OnClickListener inside view holder or creating and interface and implementing interface in your activity.. I used this code for simple on OnClickListener implementation.

 public static class SimpleStringRecyclerViewAdapter extends RecyclerView.Adapter { // Your initializations goes here... private List mValues; public static class ViewHolder extends RecyclerView.ViewHolder { //create a variable mView public final View mView; /*All your row widgets goes here public final ImageView mImageView; public final TextView mTextView;*/ public ViewHolder(View view) { super(view); //Initialize it here mView = view; /* your row widgets initializations goes here mImageView = (ImageView) view.findViewById(R.id.avatar); mTextView = (TextView) view.findViewById(android.R.id.text1);*/ } } public String getValueAt(int position) { return mValues.get(position); } public SimpleStringRecyclerViewAdapter(Context context, List items) { mBackground = mTypedValue.resourceId; mValues = items; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.list_item, parent, false); view.setBackgroundResource(mBackground); return new ViewHolder(view); } @Override public void onBindViewHolder(final ViewHolder holder, int position) { holder.mBoundString = mValues.get(position); holder.mTextView.setText(mValues.get(position)); //Here it is simply write onItemClick listener here holder.mView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Context context = v.getContext(); Intent intent = new Intent(context, ExampleActivity.class); context.startActivity(intent); } }); } @Override public int getItemCount() { return mValues.size(); } } 

use PlaceHolderView

 @Layout(R.layout.item_view_1) public class View1{ @View(R.id.txt) public TextView txt; @Resolve public void onResolved() { txt.setText(String.valueOf(System.currentTimeMillis() / 1000)); } @Click(R.id.btn) public void onClick(){ txt.setText(String.valueOf(System.currentTimeMillis() / 1000)); } } 

I wrote a library to handle android recycler view item click event. You can find whole tutorial in https://github.com/ChathuraHettiarachchi/RecycleClick

 RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemClickListener(new RecycleClick.OnItemClickListener() { @Override public void onItemClicked(RecyclerView recyclerView, int position, View v) { // YOUR CODE } }); 

or to handle item long press you can use

 RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemLongClickListener(new RecycleClick.OnItemLongClickListener() { @Override public boolean onItemLongClicked(RecyclerView recyclerView, int position, View v) { // YOUR CODE return true; } }); 

recyclerview animation has not been tested, the other is normal. I think it has been optimized to the maximum. Interface has other uses, you can temporarily ignore.

 public abstract class BaseAdapterRV extends RecyclerView.Adapter implements AdapterInterface { public final String TAG = getClass().getSimpleName(); protected final Activity mActivity; protected final LayoutInflater mInflater; protected ItemClickInterface< ?, Integer> mListener; public BaseAdapterRV(Activity activity) { mActivity = activity; mInflater = LayoutInflater.from(mActivity); } @Override public final VH onCreateViewHolder(ViewGroup parent, int viewType) { return onCreateViewHolder(parent, viewType, mInflater); } @Override public final void onBindViewHolder(VH holder, int position) { holder.itemView.setTag(R.id.tag_view_click, position); //创建点击事件holder.itemView.setOnClickListener(mListener); holder.itemView.setOnLongClickListener(mListener); onBindVH(holder, position); } /////////////////////////////////////////////////////////////////////////// // 以下是增加的方法/////////////////////////////////////////////////////////////////////////// /** * 注意!涉及到notifyItemInserted刷新时立即获取position可能会不正确* 里面也有onItemLongClick */ public void setOnItemClickListener(ItemClickInterface< ?, Integer> listener) { mListener = listener; notifyDataSetChanged(); } @NonNull protected abstract VH onCreateViewHolder(ViewGroup parent, int viewType, LayoutInflater inflater); protected abstract void onBindVH(VH holder, int position); } 

This is Interface

 /** * OnItemClickListener的接口* 见子类实现{@link OnItemClickListener}{@link OnItemItemClickListener} */ public interface ItemClickInterface extends View.OnClickListener, View.OnLongClickListener { void onItemClick(DATA1 data1, DATA2 data2); boolean onItemLongClick(DATA1 data1, DATA2 data2); } 

This is an abstract class

 public abstract class OnItemClickListener implements ItemClickInterface { @Override public void onClick(View v) { onItemClick(v, (DATA) v.getTag(R.id.tag_view_click)); } @Override public boolean onLongClick(View v) { return onItemLongClick(v, (DATA) v.getTag(R.id.tag_view_click)); } @Override public boolean onItemLongClick(View view, DATA data) { return false; } } 

You only need it

  mAdapter.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(View view, Integer integer) { } @Override public boolean onItemLongClick(View view, Integer integer) { return true; } }); 

Example with getTag()/setTag() and single click listener for whole adapter:

 public class MyAdapter extends RecyclerView.Adapter { String[] mDataset = { "One", "Two", "Three" }; private final View.OnClickListener mClickListener = new View.OnClickListener() { @Override public void onClick(View v) { Object tag_pos = v.getTag(R.id.TAG_POSITION); if(tag_pos != null && tag_pos instanceof Integer) { // here is your position in the dataset that was clicked int position = (Integer) tag_pos; ... } } }; class MyViewHolder extends RecyclerView.ViewHolder { View mItemView; TextView mTextView; // as example ... MyViewHolder(View itemLayoutView){ super(itemLayoutView); mItemView = itemLayoutView; mTextView = itemLayoutView.findViewById(R.id.my_text_view_id); .... itemLayoutView.setOnClickListener(mClickListener); } } // Provide a suitable constructor (depends on the kind of dataset) public MyAdapter(String[] myDataset) { mDataset = myDataset; } @Override public void onBindViewHolder(final ViewHolder holder, int position) { // you could use getTag() here for to get previous position // that used the holder and for example cancel prev async requests // to load images for the old position or so. // // setTag() new position that use the holder, so then user // will click on the itemView - you will be able to get // the position by getTag() holder.mItemView.setTag(R.id.TAG_POSITION, position); // - get element from your dataset at this position // - replace the contents of the view with that element holder.mTextView.setText(mDataset[position]); } @Override public @NonNull MyAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View item_layout = LayoutInflater.from(parent.getContext()) .inflate(R.layout.my_recyclerview_item_layout, parent, false); .... return new MyViewHolder(item_layout); } @Override public int getItemCount() { return mDataset.length; } } 

The TAG_POSITION defined in tags.xml file as

  < ?xml version="1.0" encoding="utf-8"?>