Android RecyclerView adding and removing items

I have a RecyclerView with a TextView text box and an ImageView cross button. I have a button outside of recyclerview that makes the ImageView cross-button visible / remote.

I am looking to remove an item from recylerview when the CrossView ImageView button is clicked.

My adapter:

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

My layout:

 <?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> 

How can I get something like onClick working for my crossButton ImageView? Is there a better way? Perhaps changing the whole onclick element to delete the element? The recyclerview shows a list of places that need to be edited. Any technical advice or comments / suggestions on best implementation would be greatly appreciated.

+123
java android user-interface android-recyclerview selection
Sep 27 '14 at 16:51
source share
15 answers

I did something like that. In your 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()); } 

Hope this helps.

Edit:

getPosition() deprecated, use getAdapterPosition() .

+227
Oct. 11 '14 at 3:06
source share

First of all, the item must be removed from the list!

  mDataSet.remove(getAdapterPosition()); 

then

  notifyItemRemoved(getAdapterPosition()); notifyItemRangeChanged(getAdapterPosition(),mDataSet.size()); 
+47
Jul 03 '16 at 7:55
source share

if an item that has not been deleted uses this magic method :)

 private void deleteItem(int position) { mDataSet.remove(position); notifyItemRemoved(position); notifyItemRangeChanged(position, mDataSet.size()); holder.itemView.setVisibility(View.GONE); } 
+18
Nov 20 '16 at 22:59
source share

Perhaps a duplicate answer, but very useful to me. You can implement the method below in RecyclerView.Adapter<RecyclerView.ViewHolder> and you can use this method according to your requirements, I hope that it works for you.

 public void removeItem(@NonNull Object object) { mDataSetList.remove(object); notifyDataSetChanged(); } 
+6
Aug 26 '17 at 20:59 on
source share

In fact, with the previously mentioned code (which you can find here below), all RecyclerView child elements are animated when one element is deleted, and this is not an adaptive solution at all, including due to potential hidden problems.

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

Instead, the following snippet will only play the animation for the child being deleted, and for my part, it stopped IndexOutOfBoundException marked by the debugger as "data mismatch."

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

If we delve into the RecyclerView class, we can find a piece of javadoc that has an explanation, indeed, as the second parameter, we must pass the number of elements that are removed from the data set, and not the total number of elements

  /** * 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
Jun 19 '18 at 11:15
source share

I tried all of the above answers, but inserting or deleting elements for recyclerview causes a problem with the position in the dataset. Ended using delete(getAdapterPosition()); inside viewHolder, which did a great job of finding the position of the elements.

+4
Jul 07 '16 at 7:11
source share

The problem was that I was removing the item from the list that was no longer associated with the adapter, to make sure that you are modifying the correct adapter, which you can implement in the adapter this way:

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

And name it in your fragment or action as follows:

 adapter.removeItemAtPosition(position); 
+3
Sep 29 '16 at 17:29
source share

Here are some illustrative additional examples. See my more complete answer for examples of adding and removing a range.

Add one item

Add “Pig” to index 2 .

Insert single item

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

Delete one item

Remove "Pig" from the list.

Remove single item

 int removeIndex = 2; data.remove(removeIndex); adapter.notifyItemRemoved(removeIndex); 
+3
Feb 24 '18 at 4:15
source share
  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(); }} 

I hope this helps you.

+2
Jan 24 '19 at 13:53
source share
  String str = arrayList.get(position); arrayList.remove(str); MyAdapter.this.notifyDataSetChanged(); 
+1
Sep 29 '17 at 5:58 on
source share

if you want to delete an element, you must do this: first delete the element:

 phones.remove(position); 

in the next step, you should notify your recycler adapter that you are deleting the element by this code:

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

but if you change the element, do the following: first change the parameter of your object as follows:

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

or a new one, it looks like this:

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

then inform the adapter of your recycler that you are modifying by this code:

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

I hope it helps you.

+1
Oct. 25 '17 at 10:58 on
source share

Incase Anyone who wants to implement something similar in the Main class instead of the Adapter class, you can use 'public void removeAt (int position) {peopleListUser.remove (position);

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

where friendsListRecycler is the name of the adapter

+1
Feb 08 '19 at 15:52
source share
  //////// 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
Jul 10 '18 at 5:27
source share

make the interface into the user class of the adapter and handle the click event in the processor view.

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

after defining the adapter and binding to the processor view, called below code.

  adapter.setOnItemClickListner(new CommentsAdapter.onItemClickListner() { @Override public void onClick(Contact contact) { contectList.remove(contectList.get(contectList.indexOf(contact))); adapter.notifyDataSetChanged(); } }); } 
0
Aug 21 '18 at 7:34
source share

onBindViewHolder method write this 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
Jul 13 '19 at 13:41
source share



All Articles