¿Cómo puedo obtener la posición seleccionada en un RecyclerView?

Estoy experimentando con el recyclerview y las tarjetas de la biblioteca de soporte. Tengo un reciclerview de tarjetas. Cada tarjeta tiene un icono 'x' en la esquina superior derecha para eliminarlo:

La tarjeta 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) etiquetar la fila con la posición que usaría en notifyItemRemoved(position) en 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); } } 

Esto no funcionará porque no puede establecer una etiqueta ni puedo acceder al adaptador desde onClick.

    Establezca los oyentes onClick en onBindViewHolder y puede acceder a la posición desde allí. Si los configura en su ViewHolder no sabrá a qué posición se ha hecho clic a menos que también pase la posición en el ViewHolder

    EDITAR

    Como pskink señaló ViewHolder tiene un getPosition por lo que la forma en que originalmente lo hacía era correcta.

    Cuando se hace clic en la vista puede utilizar getPosition en su ViewHolder y devuelve la posición

    Actualizar

    getPosition() ahora está obsoleto y se sustituye por getAdapterPosition()

    Un método diferente – usando los métodos setTag () y getTag () de la clase View.

    1. Use setTag () en el método onBindViewHolder de su adaptador

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

      Donde mCardView se define en la clase 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. Use getTag () en su implementación 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(); } 

    Consulte https://stackoverflow.com/a/33027953/4658957 para obtener más información

    Para complementar @tyczj respuesta:

    Generic Adapter Pseido código:

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

    Uso del adaptador:

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

    Consiga el niño enfocado, y utilícelo para conseguir la posición en adaptador.

     mRecyclerView.getChildAdapterPosition(mRecyclerView.getFocusedChild()) 

    Personalmente, la forma más simple que he encontrado y funciona muy bien para mí es la siguiente:

    Crear una interfaz dentro de su "RecycleAdapter" Clase (Subclase)

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

    Agregue una variable de la interfaz como un parámetro en el Constructor.

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

    Establezca un listener Click en el ViewHolder (otra subclase) y pase la 'posición' a través de la interfaz

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

    Ahora, al inicializar el adaptador de reciclador en una actividad / fragmento, sólo cree un nuevo 'ClickCallback' (interfaz)

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

    Eso es todo para mí. 🙂

    He resuelto de esta manera

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

    Y en el adaptador

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

    Creo que la forma más correcta de obtener la posición del artículo es

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

    Debido a la vista, no hace clic siempre en la vista raíz de su diseño de fila. Si la vista no es una raíz (por ejemplo, botones), obtendrá la excepción Cast de clase. Así, al principio tenemos que encontrar la opinión, que es el niño dirrect de usted reciclerview. Luego, encuentre la posición usando recyclerView.getChildAdapterPosition (view);

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.