Haz clic en el elemento y su posición en RecyclerView

Estoy reemplazando mi ListView con RecyclerView , la lista muestra bien, pero me gustaría saber cómo hacer clic en el elemento y su posición, de forma similar al método OnItemClickListener.onItemClick(AdapterView parent, View v, int position, long id) que usamos en ListView .

Gracias por las ideas!

Basado en el enlace: ¿Por qué RecyclerView no tiene onItemClickListener ()? y ¿Cómo RecyclerView es diferente de Listview? , y también la idea general de @Duncan, doy mi solución aquí:

  • Defina una interfaz RecyclerViewClickListener para pasar el mensaje del adaptador a la Activity / Fragment :

     public interface RecyclerViewClickListener { public void recyclerViewListClicked(View v, int position); } 
  • En Activity / Fragment implemente la interfaz y también pase el listener al adaptador:

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

     public class MyRecyclerViewAdapter extends RecyclerView.Adapter { ... ... 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()); } } } 

Después de la prueba, funciona bien.

[ ACTUALIZAR ]

Desde API 22, RecyclerView.ViewHoler.getPosition() está en desuso, por lo que en su lugar con getLayoutPosition() .

 public class MyRvAdapter extends RecyclerView.Adapter{ public Context context; public ArrayList 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(); } } }); } } } 

Aquí hay un Ejemplo para configurar un Oyente Click.

 Adapter extends RecyclerView.Adapter { ... } 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; } } } 

Ponga este código donde define la vista de reciclador en la actividad.

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

Luego haga una clase separada y coloque este código:

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

Si desea hacer clic en evento de reciclaje-Vista de actividad / fragmento en lugar de adaptador, entonces también puede usar el siguiente acceso directo.

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

También puedes usar otras formas largas como usar la interfaz

 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 no proporciona dicho método.

Para administrar los eventos de clics en RecyclerView, terminé implementando onClickListener en mi adaptador, al vincular el ViewHolder: en mi ViewHolder guardo una referencia a la vista de raíz (como se puede hacer con sus ImageViews, TextViews, etc.) y al enlazar the viewHolder le puse una etiqueta con la información que necesito manejar, haga clic (como posición) y un clicklistener

Use el siguiente código: –

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

Intenta de esta manera

Clase de adaptador:

  public class ContentAdapter extends RecyclerView.Adapter { public interface OnItemClickListener { void onItemClick(ContentItem item); } private final List items; private final OnItemClickListener listener; public ContentAdapter(List 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); } }); } } 

}

En tu actividad o fragmento:

 ContentAdapter adapter = new ContentAdapter(itemList, this); 

Nota: Implemente el OnItemClickListener en función del contexto dado por usted en los métodos de actividad o fragmento y alternativa.

Cada vez que uso otro enfoque. Las personas parecen almacenar u obtener una posición en una vista, en lugar de almacenar una referencia a un objeto que ViewHolder muestra.

En su lugar, uso este enfoque, y simplemente lo almaceno en ViewHolder cuando se invoca onBindViewHolder (), y establezco la referencia a null en onViewRecycled ().

Cada vez que ViewHolder se vuelve invisible, se recicla. Entonces esto no afecta el consumo de memoria grande.

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

Extensión corta para Kotlin
El método devuelve la posición absoluta de todos los elementos (no la posición de solo los elementos visibles).

 fun RecyclerView.getChildPositionAt(x: Float, y: Float): Int { return getChildAdapterPosition(findChildViewUnder(x, y)) } 

Y uso

 val position = recyclerView.getChildPositionAt(event.x, event.y) 

Esta es la forma más sencilla y fácil de encontrar la posición del elemento cliqueado:

También he enfrentado el mismo problema.

Quería encontrar la posición del ítem cliqueado / seleccionado de RecyclerView () y realizar algunas operaciones específicas en ese ítem en particular.

El método getAdapterPosition () funciona como un amuleto para este tipo de cosas. Encontré este método después de un día de larga investigación y después de probar muchos otros métodos.

 int position = getAdapterPosition(); Toast.makeText(this, "Position is: "+position, Toast.LENGTH_SHORT).show(); 

No tiene que usar ningún método adicional. Simplemente cree una variable global llamada ‘posición’ e inicialícela con getAdapterPosition () en cualquiera de los métodos principales del adaptador (clase o similar).

Aquí hay una breve documentación de este enlace .

getAdapterPosition agregado en la versión 22.1.0 int getAdapterPosition () Devuelve la posición del adaptador del elemento representado por este ViewHolder. Tenga en cuenta que esto podría ser diferente de getLayoutPosition () si hay actualizaciones de adaptador pendientes, pero un nuevo pase de diseño aún no ha sucedido. RecyclerView no maneja ninguna actualización de adaptador hasta el siguiente recorrido de disposición. Esto puede crear inconsistencias temporales entre lo que el usuario ve en la pantalla y los contenidos del adaptador. Esta incoherencia no es importante, ya que será inferior a 16 ms, pero podría ser un problema si desea utilizar la posición de ViewHolder para acceder al adaptador. A veces, es posible que necesite obtener la posición exacta del adaptador para realizar algunas acciones en respuesta a los eventos del usuario. En ese caso, debe usar este método que calculará la posición del Adaptador del ViewHolder.

Feliz de ayudar. Siéntase libre de preguntar dudas.

Use getLayoutPosition () en su interfaz personalizada con el método de Java. Esto devolverá la posición seleccionada de un artículo, verifique el detalle completo en

https://becody.com/get-clicked-item-and-its-position-in-recyclerview/

En onViewHolder, configure onClickListiner en cualquier vista y en clic lateral use este código:

Toast.makeText (Drawer_bar.this, “posición” + posición, Toast.LENGTH_SHORT) .show ();

Reemplace Drawer_Bar con su nombre de actividad.