获得点击项目及其在RecyclerView中的位置

我用RecyclerViewreplace我的ListView ,列表显示好,但我想知道如何获得点击项目和它的位置,类似于我们使用的方法OnItemClickListener.onItemClick(AdapterView parent, View v, int position, long id) ListView

感谢您的想法!

基于链接: 为什么RecyclerView没有onItemClickListener()? 以及如何RecyclerView不同于列表视图? ,还有邓肯的总体想法,我在这里给出我的解决scheme:

  • 定义一个接口RecyclerViewClickListener将消息从适配器传递给Activity / Fragment

     public interface RecyclerViewClickListener { public void recyclerViewListClicked(View v, int position); } 
  • Activity / Fragment实现接口,并将侦听器传递给适配器:

     @Override public void recyclerViewListClicked(View v, int position){... ...} //set up adapter and pass clicked listener this myAdapter = new MyRecyclerViewAdapter(context, this); 
  • AdapterViewHolder

     public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ItemViewHolder> { ... ... private Context context; private static RecyclerViewClickListener itemListener; public MyRecyclerViewAdapter(Context context, RecyclerViewClickListener itemListener) { this.context = context; this.itemListener = itemListener; ... ... } //ViewHolder class implement OnClickListener, //set clicklistener to itemView and, //send message back to Activity/Fragment public static class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ ... ... public ItemViewHolder(View convertView) { super(convertView); ... ... convertView.setOnClickListener(this); } @Override public void onClick(View v) { itemListener.recyclerViewListClicked(v, this.getPosition()); } } } 

经过testing,它工作正常。

[ 更新 ]

由于API 22, RecyclerView.ViewHoler.getPosition()已被弃用,所以使用getLayoutPosition()

 public class MyRvAdapter extends RecyclerView.Adapter<MyRvAdapter.MyViewHolder>{ public Context context; public ArrayList<RvDataItem> dataItems; ... constructor overrides ... class MyViewHolder extends RecyclerView.ViewHolder{ public TextView textView; public Context context; public MyViewHolder(View itemView, Context context) { super(itemView); this.context = context; this.textView = (TextView)itemView.findViewById(R.id.textView); // on item click itemView.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v) { // get position int pos = getAdapterPosition(); // check if item still exists if(pos != RecyclerView.NO_POSITION){ RvDataItem clickedDataItem = dataItems.get(pos); Toast.makeText(v.getContext(), "You clicked " + clickedDataItem.getName(), Toast.LENGTH_SHORT).show(); } } }); } } } 

这里是一个设置Click Listener的例子。

 Adapter extends RecyclerView.Adapter<MessageAdapter.MessageViewHolder> { ... } public static class MessageViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public TextView tv_msg; public TextView tv_date; public TextView tv_sendTime; public ImageView sharedFile; public ProgressBar sendingProgressBar; public MessageViewHolder(View v) { super(v); tv_msg = (TextView) v.findViewById(R.id.tv_msg); tv_date = (TextView) v.findViewById(R.id.tv_date); tv_sendTime = (TextView) v.findViewById(R.id.tv_sendTime); sendingProgressBar = (ProgressBar) v.findViewById(R.id.sendingProgressBar); sharedFile = (ImageView) v.findViewById(R.id.sharedFile); sharedFile.setOnClickListener(this); } @Override public void onClick(View view) { int position = getAdapterPosition(); switch (view.getId()){ case R.id.sharedFile: Log.w("", "Selected"+position); break; } } } 

如果你想要回收的Click事件 – 从活动/片段而不是适配器,那么你也可以使用下面的捷径。

 recyclerView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { final TextView txtStatusChange = (TextView)v.findViewById(R.id.txt_key_status); txtStatusChange.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e(TAG, "hello text " + txtStatusChange.getText().toString() + " TAG " + txtStatusChange.getTag().toString()); Util.showToast(CampaignLiveActivity.this,"hello"); } }); return false; } }); 

您也可以使用其他很长的方式,如使用界面

我有一个解决scheme,把这个代码放在活动中定义回收视图的地方。

  rv_list.addOnItemTouchListener( new RecyclerItemClickListener(activity, new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View v, int position) { Toast.makeText(activity, "" + position, Toast.LENGTH_SHORT).show(); } }) ); 

然后做出单独的类,把这个代码,

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

它的工作原理。我希望它也能解决你的问题…如果我的答案是正确的,然后plz打勾作为一个权利… … –

 recyclerViewObject.addOnItemTouchListener( new RecyclerItemClickListener( getContext(), recyclerViewObject, new RecyclerItemClickListener.OnItemClickListener() { @Override public void onItemClick(View view, int position) { // view is the clicked view (the one you wanted // position is its position in the adapter } @Override public void onLongItemClick(View view, int position) { } } ) ); 

RecyclerView不提供这样的方法。

为了pipe理RecyclerView上的点击事件,当绑定ViewHolder时,我终于在适配器中实现了onClickListener:在ViewHolder中,我保留对根视图的引用(就像你可以对ImageView,TextViews等做的那样) viewHolder我设置了一个标签,我需要处理点击(如位置)和clicklistener的信息

使用下面的代码: –

 public class SergejAdapter extends RecyclerView.Adapter<SergejAdapter.MyViewHolder>{ ... class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ @Override public void onClick(View v) { // here you use position int position = getAdapterPosition(); ... } } } 
 //Create below methods into the Activity which contains RecyclerView. private void createRecyclerView() { final RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView); recyclerView.setLayoutManager(new LinearLayoutManager(this)); MyAdapter myAdapter=new MyAdapter(dataAray,MianActivity.this); recyclerView.setAdapter(myAdapter); recyclerView.setItemAnimator(new DefaultItemAnimator()); setRecyclerViewClickListner(recyclerView); } private void setRecyclerViewClickListner(RecyclerView recyclerView){ final GestureDetector gestureDetector = new GestureDetector(MainActivity.this,new GestureDetector.SimpleOnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { return true; } }); recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() { @Override public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) { View child =recyclerView.findChildViewUnder(motionEvent.getX(),motionEvent.getY()); if(child!=null && gestureDetector.onTouchEvent(motionEvent)){ int position=recyclerView.getChildLayoutPosition(child); String name=itemArray.get(position).name; return true; } @Override public void onTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean b) { } }); } 

试试这样

适配器类:

  public class ContentAdapter extends RecyclerView.Adapter<ContentAdapter.ViewHolder> { public interface OnItemClickListener { void onItemClick(ContentItem item); } private final List<ContentItem> items; private final OnItemClickListener listener; public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) { this.items = items; this.listener = listener; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_item, parent, false); return new ViewHolder(v); } @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.bind(items.get(position), listener); } @Override public int getItemCount() { return items.size(); } static class ViewHolder extends RecyclerView.ViewHolder { private TextView name; private ImageView image; public ViewHolder(View itemView) { super(itemView); name = (TextView) itemView.findViewById(R.id.name); image = (ImageView) itemView.findViewById(R.id.image); } public void bind(final ContentItem item, final OnItemClickListener listener) { name.setText(item.name); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.onItemClick(item); } }); } } 

}

在您的活动或片段中:

 ContentAdapter adapter = new ContentAdapter(itemList, this); 

注意:根据您在活动或片段中提供的上下文和覆盖方法实现OnItemClickListener。

每次我使用另一种方法。 人们似乎在视图上存储或获取位置,而不是存储对由ViewHolder显示的对象的引用。

我使用这种方法,并调用onBindViewHolder()时将其存储在ViewHolder中,并在onViewRecycled()中将引用设置为null。

每次ViewHolder变得不可见时,它都会被回收。 所以这不会影响大内存的消耗。

 @Override public void onBindViewHolder(final ItemViewHolder holder, int position) { ... holder.displayedItem = adapterItemsList.get(i); ... } @Override public void onViewRecycled(ItemViewHolder holder) { ... holder.displayedItem = null; ... } class ItemViewHolder extends RecyclerView.ViewHolder { ... MySuperItemObject displayedItem = null; ... } 
 Toast.makeText(Drawer_bar.this, "position" + position, Toast.LENGTH_SHORT).show(); 

Drawer_Barreplace为您的活动名称。