Cómo utilizar OnClickListner en CardView en un RecyclerView?

Intento hacer algo como esto: Introduzca aquí la descripción de la imagen

Mi problema y cuando hago clic en mi ImageView , mi CardView se expande, pero el n-th CardView también se expande que toma el CardView ampliado en el que hice clic. No entiendo por qué mi método onClick también se aplica al otro CardView .

Mi adaptador

 public class CardsViewAdapter extends RecyclerView.Adapter<CardsViewAdapter.ViewHolder> { private Game[] mDataset; int rotationAngle = 0; // Provide a reference to the views for each data item // Complex data items may need more than one view per item, and // you provide access to all the views for a data item in a view holder public static class ViewHolder extends RecyclerView.ViewHolder { // each data item is just a string in this case public TextView mTextView; public ImageView imageView; public LinearLayout test2; public TextView test3; boolean isPopupVisible; public ViewHolder(View v) { super(v); mTextView = (TextView) v.findViewById(R.id.text_cards); imageView = (ImageView) v.findViewById(R.id.item_description_game_more); test2 = (LinearLayout) v.findViewById(R.id.popup_layout); test3 = (TextView) v.findViewById(R.id.test_view); isPopupVisible = false; } } // Provide a suitable constructor (depends on the kind of dataset) public CardsViewAdapter(Game[] myDataset) { mDataset = myDataset; } // Create new views (invoked by the layout manager) @Override public CardsViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // create a new view View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.cards_resume_game, parent, false); // set the view's size, margins, paddings and layout parameters //... ViewHolder vh = new ViewHolder(v); return vh; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(final ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element //TODO : complete final int pos = position; holder.mTextView.setText(String.valueOf(mDataset[position].getId_game())); holder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d("POS","actual pos = "+pos); holder.test3.setText("Position : "+pos); // Perform action on click if (holder.isPopupVisible) { holder.isPopupVisible = false; ObjectAnimator anim = ObjectAnimator.ofFloat(v, "rotation",rotationAngle, rotationAngle + 180); anim.setDuration(500); anim.start(); rotationAngle += 180; rotationAngle = rotationAngle%360; CardsAnimationHelper.collapse(holder.test2); } else { holder.isPopupVisible = true; ObjectAnimator anim = ObjectAnimator.ofFloat(v, "rotation",rotationAngle, rotationAngle + 180); anim.setDuration(500); anim.start(); rotationAngle += 180; rotationAngle = rotationAngle%360; CardsAnimationHelper.expand(holder.test2); } } }); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return mDataset.length; } } 

Creo que ya tienes tu clase de Game . Simplemente agregue un atributo nuevo en esa clase llamada expanded .

 public Class Game { public int id; public String description; // Add an extra attribute to track the checked status // By default, set the checked status to false public boolean expanded = false; } 

Ahora, ya que ahora tiene un atributo para realizar un seguimiento del estado expandido, puede hacer fácilmente algo como esto.

 @Override public void onBindViewHolder(final ViewHolder holder, int position) { final int pos = position; holder.mTextView.setText(String.valueOf(mDataset[position].id)); // Set the expanded or collapsed mode here if(mDataset[position].expanded) expandView(holder.test2); else collapseView(holder.test2); // Now set the onClickListener like this holder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { holder.test3.setText("Position : "+pos); // Animate the imageView here animateImageView(holder.imageView); // Toggle the expanded attribute value if(mDataset[position].expanded) mDataset[position].expanded = false; else mDataset[position].expanded = true; // Now call notifyDataSetChanged to make the change to effect refreshList(); } }); } // Extra functions inside your adapter class to improve readability private void collapseView(View view) { CardsAnimationHelper.collapse(view); } private void expandView(View view) { CardsAnimationHelper.expand(view); } private void animateImageView(ImageView imageView) { ObjectAnimator anim = ObjectAnimator.ofFloat(imageView, "rotation",rotationAngle, rotationAngle + 180); anim.setDuration(animationDuration); anim.start(); rotationAngle += 180; rotationAngle = rotationAngle % 360; } long animationDuration = 500; private void refreshList() { final Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { notifyDataSetChanged(); } }, animationDuration); } 

La razón por la que esto sucede es porque el n-ésimo elemento de su lista está reutilizando la vista que expandió. Eso es lo que el titular de la vista es, para reutilizar las vistas y no crearlas cada vez.

Para que usted pueda arreglar que asegúrese de comprobar el estado expandido de su vista enBindViewHolder de nuevo y no sólo onClick.

Agregue PopupVisible a su clase de juego como una variable y en onBindViewHolder expandió el cardview sólo cuando game.getPopupVisible es true:

 public class CardsViewAdapter extends RecyclerView.Adapter<CardsViewAdapter.ViewHolder> { private Game[] mDataset; int rotationAngle = 0; // Provide a reference to the views for each data item // Complex data items may need more than one view per item, and // you provide access to all the views for a data item in a view holder public static class ViewHolder extends RecyclerView.ViewHolder { // each data item is just a string in this case public TextView mTextView; public ImageView imageView; public LinearLayout test2; public TextView test3; public ViewHolder(View v) { super(v); mTextView = (TextView) v.findViewById(R.id.text_cards); imageView = (ImageView) v.findViewById(R.id.item_description_game_more); test2 = (LinearLayout) v.findViewById(R.id.popup_layout); test3 = (TextView) v.findViewById(R.id.test_view); } } // Provide a suitable constructor (depends on the kind of dataset) public CardsViewAdapter(Game[] myDataset) { mDataset = myDataset; } // Create new views (invoked by the layout manager) @Override public CardsViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // create a new view View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.cards_resume_game, parent, false); // set the view's size, margins, paddings and layout parameters //... ViewHolder vh = new ViewHolder(v); return vh; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(final ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element //TODO : complete final int pos = position; Game game=mDataset[position]; holder.mTextView.setText(String.valueOf(mDataset[position].getId_game())); if (game.getPopupVisible()) { ObjectAnimator anim = ObjectAnimator.ofFloat(v, "rotation",rotationAngle, rotationAngle + 180); anim.setDuration(500); anim.start(); rotationAngle += 180; rotationAngle = rotationAngle%360; CardsAnimationHelper.collapse(holder.test2);} else.... holder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d("POS","actual pos = "+pos); holder.test3.setText("Position : "+pos); // Perform action on click if (game.getPopupVisible()) { game.setPopupVisible(false); ObjectAnimator anim = ObjectAnimator.ofFloat(v, "rotation",rotationAngle, rotationAngle + 180); anim.setDuration(500); anim.start(); rotationAngle += 180; rotationAngle = rotationAngle%360; CardsAnimationHelper.collapse(holder.test2); } else { game.setPopupVisible(true); ObjectAnimator anim = ObjectAnimator.ofFloat(v, "rotation",rotationAngle, rotationAngle + 180); anim.setDuration(500); anim.start(); rotationAngle += 180; rotationAngle = rotationAngle%360; CardsAnimationHelper.expand(holder.test2); } } }); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { return mDataset.length; } } 
  • Diferente ancho de diseño dentro de RecyclerView y LinearLayout normal
  • Obtener el ancho de CardView en Adapter.onBindViewHolder
  • ¿Cómo saber cuando el RecyclerView ha terminado de colocar los artículos?
  • Cómo crear una barra de herramientas de la tarjeta usando appcompat v7
  • Diferentes resultados de CardView de la Biblioteca de soporte de Android en diferentes dispositivos
  • Expanda CardView dentro de RecyclerView como nueva actividad como Inbox de Google Android
  • Población animada de RecyclerView
  • Extraño comportamiento de las imágenes en RecyclerView
  • GetAdapterPosition () no devuelve la posición del elemento en RecyclerView
  • Extraño problema de CardView: ("Error al encontrar: com.android.support:cardview-v7:21.0.+" Error)
  • RecyclerView dentro de ScrollView no funciona
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.