Как получить позицию, выбранную в RecyclerView?

Я экспериментирую с recyclerview и карточками поддержки библиотеки. У меня есть рецидивы карт. Каждая карта имеет значок «x» в верхнем правом углу, чтобы удалить его:

Карта xml, list_item.xml :

 <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/taskDesc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:textSize="40sp" android:text="hi"/> <ImageView android:id="@+id/xImg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:src="@drawable/ic_remove"/> </RelativeLayout> </android.support.v7.widget.CardView> 

Я попытался пометить строку с позицией, которую я бы использовал в notifyItemRemoved(position) в TaskAdapter.java :

 public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.TaskViewHolder> { private List<Task> taskList; private TaskAdapter thisAdapter = this; // cache of views to reduce number of findViewById calls public static class TaskViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { protected TextView taskTV; protected ImageView closeBtn; public TaskViewHolder(View v) { super(v); taskTV = (TextView)v.findViewById(R.id.taskDesc); } @Override public void onClick(View v) { int position = v.getTag(); adapter.notifyItemRemoved(position); } } public TaskAdapter(List<Task> tasks) { if(tasks == null) throw new IllegalArgumentException("tasks cannot be null"); taskList = tasks; } // onBindViewHolder binds a model to a viewholder @Override public void onBindViewHolder(TaskViewHolder taskViewHolder, int pos) { final int position = pos; Task currTask = taskList.get(pos); taskViewHolder.taskTV.setText(currTask.getDescription()); taskViewHolder.closeBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { thisAdapter.notifyItemRemoved(position); } }); } @Override public int getItemCount() { return taskList.size(); } // inflates row to create a viewHolder @Override public TaskViewHolder onCreateViewHolder(ViewGroup parent, int pos) { View itemView = LayoutInflater.from(parent.getContext()). inflate(R.layout.list_item, parent, false); return new TaskViewHolder(itemView); } } 

Это не сработает, потому что вы не можете установить тег и не можете получить доступ к адаптеру из onClick.

Solutions Collecting From Web of "Как получить позицию, выбранную в RecyclerView?"

Установите onClick-слушателей на onBindViewHolder и вы можете получить доступ к позиции оттуда. Если вы установили их в своем ViewHolder, вы не узнаете, какую позицию щелкнули, если вы также не переместили позицию в ViewHolder

РЕДАКТИРОВАТЬ

Поскольку pskink указал, что у ViewHolder есть getPosition так, как вы изначально делали это, было правильно.

Когда getPosition вы можете использовать getPosition в своем ViewHolder, и он возвращает позицию

Обновить

getPosition() теперь устарел и заменен getAdapterPosition()

Другой метод – использование методов setTag () и getTag () класса View.

  1. Используйте setTag () в методе onBindViewHolder вашего адаптера

     @Override public void onBindViewHolder(myViewHolder viewHolder, int position) { viewHolder.mCardView.setTag(position); } 

    Где mCardView определен в классе myViewHolder

     private class myViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { public View mCardView; public myViewHolder(View view) { super(view); mCardView = (CardView) view.findViewById(R.id.card_view); mCardView.setOnClickListener(this); } } 
  2. Использовать getTag () в вашей реализации OnClickListener

     @Override public void onClick(View view) { int position = (int) view.getTag(); //display toast with position of cardview in recyclerview list upon click Toast.makeText(view.getContext(),Integer.toString(position),Toast.LENGTH_SHORT).show(); } 

См. https://stackoverflow.com/a/33027953/4658957 для получения более подробной информации.

Чтобы дополнить @tyczj ответ:

Общий код Pseido Adapter:

 public abstract class GenericRecycleAdapter<T, K extends RecyclerView.ViewHolder> extends RecyclerView.Adapter{ private List<T> mList; //default implementation code public abstract int getLayout(); @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()) .inflate(getLayout(), parent, false); return getCustomHolder(v); } public Holders.TextImageHolder getCustomHolder(View v) { return new Holders.TextImageHolder(v){ @Override public void onClick(View v) { onItem(mList.get(this.getAdapterPosition())); } }; } abstract void onItem(T t); @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { onSet(mList.get(position), (K) holder); } public abstract void onSet(T item, K holder); } 

ViewHolder:

 public class Holders { public static class TextImageHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ public TextView text; public TextImageHolder(View itemView) { super(itemView); text = (TextView) itemView.findViewById(R.id.text); text.setOnClickListener(this); } @Override public void onClick(View v) { } } } 

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

 public class CategoriesAdapter extends GenericRecycleAdapter<Category, Holders.TextImageHolder> { public CategoriesAdapter(List<Category> list, Context context) { super(list, context); } @Override void onItem(Category category) { } @Override public int getLayout() { return R.layout.categories_row; } @Override public void onSet(Category item, Holders.TextImageHolder holder) { } } 
  public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { FrameLayout root; public ViewHolder(View itemView) { super(itemView); root = (FrameLayout) itemView.findViewById(R.id.root); root.setOnClickListener(this); } @Override public void onClick(View v) { LogUtils.errorLog("POS_CLICKED: ",""+getAdapterPosition()); } } 

Получите сосредоточенный ребенок и используйте его, чтобы получить положение в адаптере.

 mRecyclerView.getChildAdapterPosition(mRecyclerView.getFocusedChild()) 

Лично, самый простой способ, который я нашел и отлично работает для меня, выглядит следующим образом:

Создайте интерфейс внутри класса «RecycleAdapter» (подкласс)

 public interface ClickCallback { void onItemClick(int position); } 

Добавьте переменную интерфейса в качестве параметра в конструктор.

 private String[] items; private ClickCallback callback; public RecyclerAdapter(String[] items, ClickCallback clickCallback) { this.items = items; this.callback = clickCallback; } 

Установите прослушиватель Click в ViewHolder (другой подкласс) и передайте «позицию» через интерфейс

  AwesomeViewHolder(View itemView) { super(itemView); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { callback.onItemClick(getAdapterPosition()); } }); mTextView = (TextView) itemView.findViewById(R.id.mTextView); } 

Теперь, при инициализации адаптера recycler в действии / фрагменте, просто создайте новый «ClickCallback» (интерфейс)

 String[] values = {"Hello","World"}; RecyclerAdapter recyclerAdapter = new RecyclerAdapter(values, new RecyclerAdapter.ClickCallback() { @Override public void onItemClick(int position) { // Do anything with the item position } }); 

Это все для меня. 🙂

Я решил так

 class MyOnClickListener implements View.OnClickListener { @Override public void onClick(View v) { int itemPosition = mRecyclerView.getChildAdapterPosition(v); myResult = results.get(itemPosition); } } 

И в адаптере

 @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_wifi, parent, false); v.setOnClickListener(new MyOnClickListener()); ViewHolder vh = new ViewHolder(v); return vh; } 

Я думаю, что самый правильный способ получить позицию позиции

 View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View v) { View view = v; View parent = (View) v.getParent(); while (!(parent instanceof RecyclerView)){ view=parent; parent = (View) parent.getParent(); } int position = recyclerView.getChildAdapterPosition(view); } 

Поскольку view, вы не нажимаете не всегда корневой вид макета строки. Если представление не является корневым (например, кнопки), вы получите исключение класса. Таким образом, сначала нам нужно найти представление, которое является регрессивным ребёнком из вас reciclerview. Затем найдите позицию, используя recyclerView.getChildAdapterPosition (view);