Android RecyclerView ajout et suppression d’éléments

J’ai un RecyclerView avec une zone de texte TextView et un bouton croisé ImageView. J’ai un bouton en dehors de la recyclerview qui rend le bouton croisé ImageView visible / disparu.

Je cherche à supprimer un élément de la recylerview, lorsque ces éléments croisent le bouton ImageView est pressé.

Mon adaptateur:

public class MyAdapter extends RecyclerView.Adapter implements View.OnClickListener, View.OnLongClickListener { private ArrayList mDataset; private static Context sContext; public MyAdapter(Context context, ArrayList myDataset) { mDataset = myDataset; sContext = context; } @Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_text_view, parent, false); ViewHolder holder = new ViewHolder(v); holder.mNameTextView.setOnClickListener(MyAdapter.this); holder.mNameTextView.setOnLongClickListener(MyAdapter.this); holder.mNameTextView.setTag(holder); return holder; } @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.mNameTextView.setText(mDataset.get(position)); } @Override public int getItemCount() { return mDataset.size(); } @Override public void onClick(View view) { ViewHolder holder = (ViewHolder) view.getTag(); if (view.getId() == holder.mNameTextView.getId()) { Toast.makeText(sContext, holder.mNameTextView.getText(), Toast.LENGTH_SHORT).show(); } } @Override public boolean onLongClick(View view) { ViewHolder holder = (ViewHolder) view.getTag(); if (view.getId() == holder.mNameTextView.getId()) { mDataset.remove(holder.getPosition()); notifyDataSetChanged(); Toast.makeText(sContext, "Item " + holder.mNameTextView.getText() + " has been removed from list", Toast.LENGTH_SHORT).show(); } return false; } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView mNumberRowTextView; public TextView mNameTextView; public ViewHolder(View v) { super(v); mNameTextView = (TextView) v.findViewById(R.id.nameTextView); } } } 

Ma mise en page est:

      

Comment puis-je obtenir quelque chose comme un onClick pour mon crossButton ImageView? Y a-t-il une meilleure façon? Peut-être changer l’élément entier en un clic pour supprimer l’article? La recyclerview affiche une liste de lieux à modifier. Tout conseil technique, commentaire ou suggestion sur la meilleure mise en œuvre serait grandement apprécié.

J’ai fait quelque chose de similaire. Dans votre MyAdapter :

 public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ public CardView mCardView; public TextView mTextViewTitle; public TextView mTextViewContent; public ImageView mImageViewContentPic; //...... public ImageView imgViewRemoveIcon; public ViewHolder(View v) { super(v); mCardView = (CardView) v.findViewById(R.id.card_view); mTextViewTitle = (TextView) v.findViewById(R.id.item_title); mTextViewContent = (TextView) v.findViewById(R.id.item_content); mImageViewContentPic = (ImageView) v.findViewById(R.id.item_content_pic); //...... imgViewRemoveIcon = (ImageView) v.findViewById(R.id.remove_icon); mTextViewContent.setOnClickListener(this); imgViewRemoveIcon.setOnClickListener(this); v.setOnClickListener(this); mTextViewContent.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { if (mItemClickListener != null) { mItemClickListener.onItemClick(view, getPosition()); } return false; } }); } @Override public void onClick(View v) { //Log.d("View: ", v.toSsortingng()); //Toast.makeText(v.getContext(), mTextViewTitle.getText() + " position = " + getPosition(), Toast.LENGTH_SHORT).show(); if(v.equals(imgViewRemoveIcon)){ removeAt(getPosition()); }else if (mItemClickListener != null) { mItemClickListener.onItemClick(v, getPosition()); } } } public void setOnItemClickListener(final OnItemClickListener mItemClickListener) { this.mItemClickListener = mItemClickListener; } public void removeAt(int position) { mDataset.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, mDataSet.size()); } 

J’espère que cela t’aides.

Modifier:

getPosition() est maintenant getAdapterPosition() utilisez getAdapterPosition() .

Tout d’abord, l’article doit être retiré de la liste!

  mDataSet.remove(getAdapterPosition()); 

puis:

  notifyItemRemoved(getAdapterPosition()); notifyItemRangeChanged(getAdapterPosition(),mDataSet.size()); 

si l’article n’est toujours pas supprimé, utilisez cette méthode magique 🙂

 private void deleteItem(int position) { mDataSet.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, mDataSet.size()); holder.itemView.setVisibility(View.GONE); } 

J’ai essayé toutes les réponses ci-dessus, mais l’insertion ou la suppression d’éléments à recyclerview pose problème avec la position dans le dataSet. Terminé en utilisant delete(getAdapterPosition()); à l’intérieur du viewHolder qui a fonctionné très bien pour trouver la position des éléments.

En fait, avec le code mentionné précédemment (que vous pouvez trouver ci-dessous), tous les enfants RecyclerView sont animés lorsqu’un seul élément est supprimé et qu’il ne s’agit pas d’une solution réactive, car il comporte également des problèmes cachés potentiels.

 public void remove(int position) { dataset.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, mDataSet.size()); } 

Au lieu de cela, l’extrait suivant jouera l’animation juste sur l’enfant en cours de suppression, et de ma part il a cessé de lancer IndexOutOfBoundException s, marquée par le débogueur comme “incohérence de données”

 void remove(int position) { dataset.removeAt(position); notifyItemChanged(position); notifyItemRangeRemoved(position, 1); } 

Si nous creusons dans la classe RecyclerView , nous pouvons trouver une pièce de javadoc qui a l’explication, en effet en tant que second paramètre, nous devons passer le nombre d’éléments supprimés du jeu de données, pas le nombre total d’éléments

  /** * Notify any registered observers that the itemCount items previously * located at positionStart have been removed from the data set. The items * previously located at and after positionStart + itemCount may now be found * at oldPosition - itemCount. * * 

This is a structural change event. Representations of other existing items in the data * set are still considered up to date and will not be rebound, though their positions * may be altered.

* * @param positionStart Previous position of the first item that was removed * @param itemCount Number of items removed from the data set */ public final void notifyItemRangeRemoved(int positionStart, int itemCount) { mObservable.notifyItemRangeRemoved(positionStart, itemCount); }

Le problème que j’avais était de supprimer un élément de la liste qui n’était plus associé à l’adaptateur pour vous assurer que vous modifiez l’adaptateur correct que vous pouvez implémenter une méthode comme celle-ci dans votre adaptateur:

 public void removeItemAtPosition(int position) { items.remove(position); } 

Et appelez-le dans votre fragment ou activité comme ceci:

 adapter.removeItemAtPosition(position); 

Peut-être une réponse en double mais très utile pour moi. Vous pouvez implémenter la méthode donnée ci-dessous dans RecyclerView.Adapter et pouvez utiliser cette méthode selon vos besoins, j’espère que cela fonctionnera pour vous

 public void removeItem(@NonNull Object object) { mDataSetList.remove(object); notifyDataSetChanged(); } 

Voici quelques exemples supplémentaires visuels. Voir ma réponse plus complète pour des exemples d’ajout et de suppression d’une plage.

Ajouter un seul article

Ajouter “Cochon” à l’index 2 .

Insérer un seul élément

 Ssortingng item = "Pig"; int insertIndex = 2; data.add(insertIndex, item); adapter.notifyItemInserted(insertIndex); 

Supprimer un seul article

Supprimer “Cochon” de la liste.

Supprimer un seul article

 int removeIndex = 2; data.remove(removeIndex); adapter.notifyItemRemoved(removeIndex); 
  Ssortingng str = arrayList.get(position); arrayList.remove(str); MyAdapter.this.notifyDataSetChanged(); 

Si vous souhaitez supprimer un élément, vous devez le faire: supprimer d’abord l’élément:

 phones.remove(position); 

à l’étape suivante, vous devez informer votre adaptateur de recyclage que vous supprimez un élément par ce code:

 notifyItemRemoved(position); notifyItemRangeChanged(position, phones.size()); 

mais si vous changez un élément, faites ceci: changez d’abord un paramètre de votre object comme ceci:

 Service s = services.get(position); s.done = "Cancel service"; services.set(position,s); 

ou nouveau comme ça:

 Service s = new Service(); services.set(position,s); 

puis informez votre adaptateur de recyclage que vous modifiez un article par ce code:

 notifyItemChanged(position); notifyItemRangeChanged(position, services.size()); 

l’espoir vous aide.

  //////// set the position holder.cancel.setTag(position); ///// click to remove an item from recycler view and an array list holder.cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int positionToRemove = (int)view.getTag(); //get the position of the view to delete stored in the tag mDataset.remove(positionToRemove); notifyDataSetChanged(); } }); 

faire l’interface avec la classe d’adaptateur personnalisée et gérer les événements de clic sur la vue du recycleur.

  onItemClickListner onItemClickListner; public void setOnItemClickListner(CommentsAdapter.onItemClickListner onItemClickListner) { this.onItemClickListner = onItemClickListner; } public interface onItemClickListner { void onClick(Contact contact);//pass your object types. } @Override public void onBindViewHolder(ItemViewHolder holder, int position) { // below code handle click event on recycler view item. holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onItemClickListner.onClick(mContectList.get(position)); } }); } 

Après définir l’adaptateur et lier dans la vue recycleur appelée ci-dessous le code.

  adapter.setOnItemClickListner(new CommentsAdapter.onItemClickListner() { @Override public void onClick(Contact contact) { contectList.remove(contectList.get(contectList.indexOf(contact))); adapter.notifyDataSetChanged(); } }); }