Почему у RecyclerView нет onItemClickListener ()?

Я изучал RecyclerView и я был удивлен, увидев, что RecyclerView не имеет onItemClickListener() . Поскольку RecyclerView расширяет

android.view.ViewGroup

И ListView расширяет

android.widget.AbsListView

, Однако я решил свою проблему, написав onClick в своем 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) { } } 

Но все же я хочу знать, почему Google удалил onItemClickListener() ?

Есть ли проблема с производительностью или что-то еще?

Tl; dr 2016 Используйте RxJava и PublishSubject для отображения наблюдаемого для кликов.

 public class ReactiveAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { String[] mDataset = { "Data", "In", "Adapter" }; private final PublishSubject<String> 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<String> getPositionClicks(){ return onClickSubject.asObservable(); } } 

Оригинальное сообщение:

С момента появления ListView , onItemClickListener был проблематичным. В тот момент, когда у вас есть прослушиватель кликов для любого из внутренних элементов, обратный вызов не запускается, но он не был уведомлен или хорошо документирован (если вообще), поэтому было много путаницы и SO-вопросов об этом.

Учитывая, что RecyclerView делает это еще дальше и не имеет понятия строки / столбца, а представляет собой произвольно установленное количество детей, они делегировали onClick каждому из них или реализации программиста.

Подумайте о Recyclerview не как замену ListView 1: 1, а скорее как более гибкий компонент для сложных случаев использования. И, как вы говорите, ваше решение – это то, что Google ожидает от вас. Теперь у вас есть адаптер, который может делегировать onClick интерфейсу, переданному конструктору, который является правильным шаблоном для ListView и 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); } } 

А затем на адаптере

 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> { 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; } ... 

Теперь рассмотрим последний фрагмент кода: onCreateViewHolder(ViewGroup parent, int viewType) подпись уже предлагает разные типы просмотров. Для каждого из них вам понадобится другой зритель, и впоследствии каждый из них может иметь другой набор кликов. Или вы можете просто создать общий зритель, который принимает любое представление и один onClickListener и соответственно применяет. Или делегируйте один уровень в оркестр, чтобы несколько фрагментов / действий имели один и тот же список с разными типами кликов. Опять же, вся гибкость на вашей стороне.

Это действительно необходимый компонент и довольно близок к тому, что до сих пор были нашими внутренними реализациями и улучшениями в ListView . Хорошо, что Google, наконец, признает это.

Мне нравится этот путь, и я использую его

внутри

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

Положил

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

И создайте этот класс в любом месте, где хотите.

 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)); } } 

Я читал раньше, что есть лучший способ, но мне нравится, что это легко и не сложно.

Альтернативное решение – это предложение, предложенное Hugo Visser , Android GDE. Он предоставил вам класс без лицензии, чтобы просто добавить свой код и использовать его.

Применение:

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

(Он также поддерживает длинные клики)

Реализация (добавленные мной комментарии):

 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); } } 

Также создайте values/ids.xml файлов values/ids.xml и поместите в него:

 <?xml version="1.0" encoding="utf-8"?> <resources> <item name="item_click_support" type="id" /> </resources> 

Этот класс работает, добавив RecyclerView.OnChildAttachStateChangeListener в RecyclerView . Этот слушатель уведомляется каждый раз, когда ребенок прикреплен или отсоединен от RecyclerView . Код использует это, чтобы добавить к представлению прослушиватель нажатий / длинных кликов. Этот слушатель спрашивает RecyclerView для RecyclerView.ViewHolder который содержит позицию.

Вы также можете адаптировать код, чтобы вернуть вам сам держатель, если вам нужно больше.

Имейте в виду, что ПОЛНОСТЬЮ прекрасно обрабатывать его в вашем адаптере, задав для каждого представления вашего списка прослушиватель кликов, как и другой предложенный ответ. Это просто не самая эффективная вещь (вы создаете нового слушателя при каждом повторном использовании представления), но он работает, и в большинстве случаев это не проблема.

О том, почему RecyclerView не имеет onItemClickListener .

RecyclerView – это набор инструментов, в отличие от старого ListView он имеет меньше возможностей для создания и большей гибкости. onItemClickListener не является единственной функцией, удаляемой из ListView. Но у него много слушателей и метод, чтобы расширить его по своему вкусу, он намного более эффективен в правильных руках;).

На мой взгляд, самая сложная функция, удаленная в RecyclerView – это быстрый прокрутка . Большинство других функций можно легко повторить.

Android Recyclerview С onItemClickListener , почему мы не можем попробовать, это работает как ListView .

Источник: ссылка

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

И установите это в 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); } }) ); 

Благодаря @marmor, я обновил свой ответ.

Я думаю, что это хорошее решение для обработки onClick () в конструкторе класса ViewHolder и передачи его родительскому классу через интерфейс OnItemClickListener .

MyAdapter.java

 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{ private LayoutInflater layoutInflater; private List<MyObject> items; private AdapterView.OnItemClickListener onItemClickListener; public MyAdapter(Context context, AdapterView.OnItemClickListener onItemClickListener, List<MyObject> 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()); } } } 

Использование адаптера в других классах:

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 } } } 

Ребята используют этот код в своем основном действии. Очень эффективный метод

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

Вот ваш класс адаптера.

 public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.UserViewHolder> { private ArrayList<User> mDataSet; OnCardClickListner onCardClickListner; public UsersAdapter(ArrayList<User> 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; } } 

После этого вы получите этот метод переопределения в своей деятельности.

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

> Как RecyclerView отличается от Listview?

Одно из отличий заключается в том, что существует класс LayoutManager с RecyclerView, с помощью которого вы можете управлять своим RecyclerView ,

Горизонтальная или вертикальная прокрутка LinearLayoutManager

GridLayout от GridLayoutManager

Разнесенный GridLayout от StaggeredGridLayoutManager

Как для горизонтальной прокрутки для RecyclerView-

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

Как собрать все вместе …

  • Обработка onClick ()
  • Курсор – RecyclerView
  • Типы ViewHolder

     public class OrderListCursorAdapter extends CursorRecyclerViewAdapter<OrderListCursorAdapter.ViewHolder> { 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, "><initFromData(data=" + data + ")"); orderId = data.getId(); vAddressStart.setText(data.getAddressStart()); vAddressEnd.setText(data.getAddressEnd()); } @Override public void onClick(View view) { if (view instanceof Button) { listener.onButtonClick((Button) view, getPosition(), this); } else { super.onClick(view); } } public interface IViewHolderClick extends ViewHolder.IViewHolderClick { public void onButtonClick(Button button, int position, ViewHolder viewHolder); } } public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { private static final String TAG = ViewHolder.class.getSimpleName(); protected long orderId; protected IViewHolderClick listener; protected TextView vAddressStart; protected TextView vAddressEnd; protected TextView vStatus; public ViewHolder(View v, IViewHolderClick listener) { super(v); this.listener = listener; v.setOnClickListener(this); vAddressStart = (TextView) v.findViewById(R.id.addressStart); vAddressEnd = (TextView) v.findViewById(R.id.addressEnd); vStatus = (TextView) v.findViewById(R.id.status); } public void initFromData(OrderData data) { Log.d(TAG, "><initFromData(data=" + data + ")"); orderId = data.getId(); vAddressStart.setText(data.getAddressStart()); vAddressEnd.setText(data.getAddressEnd()); } public long getOrderId() { return orderId; } @Override public void onClick(View view) { listener.onCardClick(view, getPosition(), this); } public interface IViewHolderClick { public void onCardClick(View view, int position, ViewHolder viewHolder); } } @Override public int getItemViewType(int position) { return position == 0 ? ID_VIEW_HOLDER_ACTUAL : ID_VIEW_HOLDER; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 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, "><onCardClick(view=" + view + ", position=" + position + ", viewHolder=" + viewHolder + ")"); Intent intent = new Intent(view.getContext(), OrderDetailActivity.class); intent.putExtra(OrderDetailActivity.ARG_ORDER_ID, viewHolder.getOrderId()); view.getContext().startActivity(intent); } @Override public void onButtonClick(Button button, int position, ViewHolder viewHolder) { Log.d(TAG, "><onButtonClick(button=" + button + ", position=" + position + ", viewHolder=" + viewHolder + ")"); Intent intent = new Intent(button.getContext(), OrderMapActivity.class); intent.putExtra(OrderMapActivity.ARG_ORDER_ID, viewHolder.getOrderId()); button.getContext().startActivity(intent); } }); break; } case ID_VIEW_HOLDER: default: { View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_layout, parent, false); result = new ViewHolder(itemView, new ViewHolder.IViewHolderClick() { @Override public void onCardClick(View view, int position, ViewHolder viewHolder) { Log.d(TAG, "><onCardClick(view=" + view + ", position=" + position + ", viewHolder=" + viewHolder + ")"); Intent intent = new Intent(view.getContext(), OrderDetailActivity.class); intent.putExtra(OrderDetailActivity.ARG_ORDER_ID, viewHolder.getOrderId()); view.getContext().startActivity(intent); } }); break; } } Log.d(TAG, "<<onCreateViewHolder(parent=" + parent + ", viewType=" + viewType + ")= " + result); return result; } @Override public void onBindViewHolder(ViewHolder viewHolder, Cursor cursor) { Log.d(TAG, "><onBindViewHolder(viewHolder=" + viewHolder + ", cursor=" + cursor + ")"); final OrderData orderData = new OrderData(cursor); viewHolder.initFromData(orderData); } } 

Насколько я понимаю ответ MLProgrammer-CiM , просто можно просто сделать это:

 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(); } } 

Прочитав ответ @ MLProgrammer-CiM , вот мой код:

 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); } } } 

Я сделал так, очень просто:

Просто добавьте 1 строку для выбранной позиции RecyclerView :

 int position = getLayoutPosition() 

Полный код для класса ViewHolder :

 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())); } }); } } 

Надеюсь, что это поможет вам.

Я использую этот метод для запуска Intent из RecyclerView:

 @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); } } ); 

Вот способ реализовать его довольно легко, если у вас есть список POJO и вы хотите получить один на клик извне адаптера.

В своем адаптере создайте прослушиватель для событий кликов и метод его установки:

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

}

В вашем ViewHolder реализуйте onClickListener и создайте члена класса для временного хранения POJO, который представляет представление, таким образом (это пример, создание сеттера было бы лучше):

 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); } } 

Вернитесь в свой адаптер, установите текущее POJO, когда объект ViewHolder привязан (или к нулевому, если текущий вид его не имеет):

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

Вот и все, теперь вы можете использовать его как это из своего фрагмента / активности:

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

Следующее превосходное решение RxJava от MLProgrammer-CiM

Потребление / Наблюдение за кликами

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

RxJava 2. +

Измените оригинал tl; dr как:

 public Observable<String> getPositionClicks(){ return onClickSubject; } 

PublishSubject#asObservable() удален. Просто верните PublishSubject который является Observable .

См. Мой подход к этому:

Сначала объявите интерфейс следующим образом:

 /** * 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<T> { /** * 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); } 

Затем создайте адаптер:

 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); } } 

А теперь давайте посмотрим, как интегрировать это из фрагмента:

 public class TestFragment extends Fragment implements OnRecyclerItemClickListener<Data>{ 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! 🙂

Это сработало для меня:

 @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() } } 

Да, ты можешь

 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<RVNewsAdapter.FeedHolder> { private Context context; List<News> newsList; // Allows to remember the last item shown on screen private int lastPosition = -1; public RVNewsAdapter(List<News> 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); } } 

адаптер

 public class RecyclerView_Adapter extends RecyclerView.Adapter<RecyclerViewHolder> { //RecyclerView will extend to recayclerview Adapter private ArrayList<ModelClass> arrayList; private Context context; private static RecyclerViewClickListener itemListener; //constructor of the RecyclerView Adapter RecyclerView_Adapter(Context context,ArrayList<ModelClass> 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]); } 

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<SimpleStringRecyclerViewAdapter.ViewHolder> { // Your initializations goes here... private List<String> 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<String> 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; } }); 

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); } }); } 

Easiest way to do this is as follows:

Declare global variable at start of Adapter class:

 // Store out here so we can resuse private View yourItemView; 

Then set the OnClickListener within the onBindViewHolder method:

  // Set up the on click listener yourItemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext,Integer.toString(position),Toast.LENGTH_SHORT).show(); } }); 

All other answers are lame.

Intereting Posts
Обратная связь Java.lang.RuntimeException: Невозможно создать экземпляр приложения: ClassNotFoundException (только на устройстве архитектуры X86) Как я могу получить позицию элемента в списке, когда я нажимаю на конкретное представление? Читатель новостей новостей Facebook на Android Как я могу использовать один и тот же набор экранов предпочтений для всех версий Android от 2.X до 4.X? UiAutomator getLastTraversedText () Android: Как правильно установить цвет текста для элементов списка в AlertDialog Snackbar не работает в классе фрагментов Загружать html-файлы из исходной папки в веб-просмотр Вызывается: java.lang.IllegalArgumentException: column '_id' не существует Запуск приложений Android в веб-браузере Код Xamarin и c ++ Как я могу избежать выпадающего списка автозаполнения, появляющегося при программном наборе текста? Как оживить значок меню переполнения панели инструментов Установить полный экран на страницеСтать