web-dev-qa-db-fra.com

Android RecyclerVoir l'ajout et le retrait d'éléments

J'ai un RecyclerView avec une zone de texte TextView et un bouton en croix ImageView. J'ai un bouton en dehors de la vue recyclée qui rend le bouton en croix ImageView visible/disparu.

Je cherche à supprimer un élément de la vue d'ensemble, lorsque vous cliquez sur le bouton ImageView.

Mon adaptateur:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> implements View.OnClickListener, View.OnLongClickListener {

    private ArrayList<String> mDataset;
    private static Context sContext;

    public MyAdapter(Context context, ArrayList<String> 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:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:orientation="horizontal"
    Android:gravity="center_vertical"
    Android:id="@+id/layout">

    <TextView
        Android:id="@+id/nameTextView"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:textSize="18sp"
        Android:padding="5dp"
        Android:background="@drawable/greyline"/>

    <ImageView
        Android:id="@+id/crossButton"
        Android:layout_width="16dp"
        Android:layout_height="16dp"
        Android:visibility="gone"
        Android:layout_marginLeft="50dp"
        Android:src="@drawable/cross" />
</LinearLayout>

Comment puis-je obtenir quelque chose comme un onClick pour mon crossButton ImageView? Y a-t-il un meilleur moyen? Peut-être changer l’ensemble de l’article lorsqu’il clique sur supprimer l’article? La vue de recyclage affiche une liste des emplacements à modifier. Tous les conseils techniques, commentaires ou suggestions sur la meilleure mise en œuvre seraient grandement appréciés.

122
Twentyonehundred

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.toString());
        //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.

Edit:

getPosition() est obsolète maintenant, utilisez getAdapterPosition() à la place.

224
paradite

tout d'abord, l'article devrait être retiré de la liste!

  mDataSet.remove(getAdapterPosition());

ensuite:

  notifyItemRemoved(getAdapterPosition());
  notifyItemRangeChanged(getAdapterPosition(),mDataSet.size());
46
Zahra.HY

si l'élément 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);
}
18
Mostafa Anter

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<RecyclerView.ViewHolder> et l'utiliser selon vos besoins, j'espère que cela fonctionnera pour vous.

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

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 que ce n'est pas une solution réactive du tout, également parce qu'il comporte 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 lira l'animation uniquement sur l'enfant qui est en train d'être supprimé, et de mon côté, il a cessé de lancer IndexOutOfBoundExceptions, marqué par le débogueur comme "incohérence des 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 contenant l'explication. En deuxième paramètre, nous devons indiquer le nombre d'éléments supprimés de l'ensemble de données, et non le nombre total d'éléments.

    /**
     * Notify any registered observers that the <code>itemCount</code> items previously
     * located at <code>positionStart</code> have been removed from the data set. The items
     * previously located at and after <code>positionStart + itemCount</code> may now be found
     * at <code>oldPosition - itemCount</code>.
     *
     * <p>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.</p>
     *
     * @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);
    }
6
Andrea Cioccarelli

J'ai essayé toutes les réponses ci-dessus, mais l'insertion ou la suppression d'éléments dans recyclerview pose un problème avec la position dans le jeu de données. Nous avons fini par utiliser delete(getAdapterPosition()); dans le viewHolder, ce qui nous a permis de trouver la position des éléments.

4
Arun

Le problème que j'ai eu était que je supprimais un élément de la liste qui n'était plus associé à l'adaptateur afin de vous assurer que vous modifiez l'adaptateur approprié, 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);
3
Horatio

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

Ajouter un article

Ajoutez "Cochon" à l'index 2.

Insert single item

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

Supprimer un seul élément

Supprimer "Cochon" de la liste.

Remove single item

int removeIndex = 2;
data.remove(removeIndex);
adapter.notifyItemRemoved(removeIndex);
3
Suragch
  public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context context;
private List<cardview_widgets> list;

public MyAdapter(Context context, List<cardview_widgets> list) {
    this.context = context;
    this.list = list;
}

@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(this.context).inflate(R.layout.fragment1_one_item,
            viewGroup, false);
    return new MyViewHolder(view);
}

public static class MyViewHolder extends RecyclerView.ViewHolder {
    TextView txt_value;
    TextView txt_category;
    ImageView img_inorex;
    ImageView img_category;
    TextView txt_date;

    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
        txt_value = itemView.findViewById(R.id.id_values);
        txt_category = itemView.findViewById(R.id.id_category);
        img_inorex = itemView.findViewById(R.id.id_inorex);
        img_category = itemView.findViewById(R.id.id_imgcategory);
        txt_date = itemView.findViewById(R.id.id_date);
    }
}

@NonNull
@Override
public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, int i) {

    myViewHolder.txt_value.setText(String.valueOf(list.get(i).getValuee()));
    myViewHolder.txt_category.setText(list.get(i).getCategory());
    myViewHolder.img_inorex.setBackgroundColor(list.get(i).getImg_inorex());
    myViewHolder.img_category.setImageResource(list.get(i).getImg_category());
    myViewHolder.txt_date.setText(list.get(i).getDate());
    myViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
        @Override
        public boolean onLongClick(View v) {
            list.remove(myViewHolder.getAdapterPosition());
            notifyDataSetChanged();
            return false;
        }
    });
}

@Override
public int getItemCount() {
    return list.size();
}}      

j'espère que cela vous aidera.

2
  String str = arrayList.get(position);
  arrayList.remove(str);
  MyAdapter.this.notifyDataSetChanged();
1
Tarun Umath

Si n'importe qui veut implémenter quelque chose comme ceci dans la classe Main au lieu de la classe Adapter, vous pouvez utiliser `public void removeAt (int position) {peopleListUser.remove (position);

    friendsListRecycler.getAdapter().notifyItemRemoved(position);
    friendsListRecycler.getAdapter().notifyItemRangeChanged(position, peopleListUser.size());
}`

où friendsListRecycler est le nom de l'adaptateur

1
Forest baba

si vous souhaitez supprimer un élément, vous devez procéder comme suit:

phones.remove(position);

à l'étape suivante, vous devez informer votre adaptateur de recycleur que vous supprimez un élément à l'aide de 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 objet 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);

informez ensuite votre adaptateur recycleur que vous modifiez un élément à l'aide de ce code:

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

l'espoir vous aide.

To Method onBindViewHolder Écrire ce code

holder.remove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Cursor del=dbAdapter.ExecuteQ("delete from TblItem where Id="+values.get(position).getId());
                values.remove(position);
                notifyDataSetChanged();
            }
        });
0
Diako Hasani

transforme l'interface en classe d'adaptateur personnalisé et gère l'événement click dans la vue Recycler.

 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 avoir défini l’adaptateur et lié à la vue Recycler appelée code ci-dessous.

        adapter.setOnItemClickListner(new CommentsAdapter.onItemClickListner() {
        @Override
        public void onClick(Contact contact) {
            contectList.remove(contectList.get(contectList.indexOf(contact)));
            adapter.notifyDataSetChanged();
        }
    });
}
0
Android Team
 //////// 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();
                }
            });
0
roshan posakya