为什么RecyclerView没有onItemClickListener()?

我正在探索RecyclerView ,我很惊讶地发现RecyclerView没有onItemClickListener() 。 因为RecyclerView延伸

android.view.ViewGroup

ListView扩展

android.widget.AbsListView

。 不过,我通过在我的RecyclerView.Adapter编写onClick来解决了我的问题:

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

是否存在性能问题或其他问题?

tl; dr 2016使用RxJava和PublishSubject来展示点击的Observable。

 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一直存在问题。 当你有一个点击监听器的任何内部元素的callback将不会被触发,但没有通知或logging(如果有的话),所以有很多困惑和SO问题。

鉴于RecyclerView更进一步,没有一个行/列的概念,而是一个任意摆放的孩子的数量,他们已经将onClick委派给他们每一个,或者程序员的实现。

Recyclerview视为不是ListView 1:1replace,而是作为复杂用例的更灵活的组件。 正如你所说,你的解决scheme是谷歌期望你的。 现在你有一个适配器,它可以委托onClick传递给构造函数的接口,这是ListViewRecyclerview的正确模式。

 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)签名已经提示不同的视图types。 对于他们中的每一个,你也需要一个不同的查看者,随后他们每个人都可以有不同的点击次数。 或者,您可以创build一个通用的视图,它可以接受任何视图,一个onClickListener并相应地应用。 或者将一个级别委托给协调器,这样几个片段/活动具有相同的具有不同点击行为的列表。 再一次,所有的灵活性都在你身边。

这是一个真正需要的组件,并且非常接近我们的内部实现和对ListView改进。 谷歌最终承认这一点很好。

我喜欢这种方式,我正在使用它

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

并在你想要的地方创build这个类

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

我以前看过有更好的方法,但我喜欢这种方式很简单,而且不复杂。

另一种解决scheme是由Android GDE Hugo Visser 提出的解决scheme。 他为你准备了一个免许可证的课程,只需放下你的代码并使用它。

用法:

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

还要创build一个文件values/ids.xml并把它放在里面:

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

该类通过将RecyclerView.OnChildAttachStateChangeListener附加到RecyclerView.OnChildAttachStateChangeListener来工作。 每次儿童从RecyclerView附着或分离时都会通知此侦听器。 该代码使用这个附加一个龙头/长按听众的视图。 该监听器向RecyclerView询问包含该位置的RecyclerView.ViewHolder

如果你需要更多的话,你也可以修改代码来让你回到持有者身上。

请记住,通过在列表的每个视图上设置一个点击监听器,就像在其他的答案中一样,在你的适配器中处理它是完全正确的。 这不是最有效率的做法(每次重新使用视图时都会创build一个新的监听器),但是它可以工作,而且在大多数情况下这不是问题。

关于为什么 RecyclerView没有onItemClickListener

RecyclerView是一个工具箱,与旧的ListView相比,它具有更less的function和更多的灵活性。 onItemClickListener不是从ListView中删除的唯一function。 但是它有很多听众和方法可以把它扩展到你喜欢的地方,它在右手上更加强大)。

在我看来, RecyclerView最复杂的function是快速滚动 。 大多数其他function可以轻松地重新实施。

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,我更新了我的答案。

我认为这是一个很好的解决scheme,处理ViewHolder类构造函数中的onClick(),并通过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有什么不同?

一个区别是有与RecyclerView的LayoutManager类,您可以通过它来pipe理您的RecyclerView

LinearLayoutManager 水平或垂直滚动

GridLayoutManager的GridLayoutManager

StaggeredGridLayoutManager交错GridLayout

就像RecyclerView的水平滚动一样,

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

如何把它放在一起的例子…

  • onClick()处理
  • 游标 – RecyclerView
  • ViewHoldertypes

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

据我所知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(); } } 

我这样做,其实很简单:

只需添加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())); } }); } } 

希望这会帮助你。

我使用这个方法从RecyclerView启动一个Intent:

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

继MLProgrammer-CiM的优秀RxJava解决scheme

消费/观察点击

 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()已被删除。 只需返回一个ObservablePublishSubject

如果您有一个POJO列表,并希望从适配器外部单击来检索一个POJO列表,则可以非常轻松地实现它。

在您的适配器中,为click事件创build一个侦听器并设置它的方法:

 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并创build一个类成员来临时存储视图呈现的POJO,这样(这是一个例子,创build一个setter会更好):

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

回到你的适配器中,当ViewHolder绑定时设置当前的POJO(如果当前视图没有,则设置为null):

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

看到我的这个方法:

首先声明一个这样的接口:

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

然后创build适配器:

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

Adapter

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

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

it worked for me. 希望它会有所帮助。 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 ?

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:

 @Override public void onBindViewHolder(BusinessAdapter.ViewHolder holder, int position) { // 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.