Prateek Sharma
Prateek Sharma

Reputation: 35

Deletion of multiple items(Including last item) from recyclerview list It throws error IndexOutOfBound

Below code to select multiple items from the Recyclerview list.

        holder.itemView.setOnLongClickListener(View.OnLongClickListener {

              //  if (selectedPosition == position) {
                 //   selectedPosition = -1
//                    notifyItemChanged(position);
               // }
                selectedPosition = position;
                isSelect = true
                notifyItemChanged(position);
                items.get(position).id?.let { it1 -> deletList.add(it1) 
}

performing delet action on the list on selected item position.

    fun removeSelectedItems(){
    mSelectedItems.sortedDescending()
    mSelectedItems.forEach{ itemIndex ->
        items.removeAt(itemIndex)
        notifyItemRemoved(itemIndex)
        notifyDataSetChanged()
    }
    mSelectedItems.clear()
}

}

On ButtonClick deleting the selected items from recycler view list

deletebutton.setOnClickListener {
                   
                    removeSelectedItems()
                    selectedPosition = RecyclerView.NO_POSITION

                }

Deleting multiple item including last item in any order until last item is selected it is throwing error index out of bound because if any item above last item get deleted list size decreases and index still remains at position? help is appreciated.

var deletList: ArrayList<String> = ArrayList()
var items: ArrayList<GetListModel>
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OutagesViewHolder {
        return OutagesViewHolder(
            LayoutInflater.from(parent!!.context).inflate(
                R.layout.chats_list_item,
                parent,
                false
            )
        )
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getItemViewType(position: Int): Int {
        return position
    }

    override fun getItemCount(): Int = items.size


    @SuppressLint("NewApi")
    override fun onBindViewHolder(holder: OutagesViewHolder, position: Int) {


        val o: Any = items.get(position)


    holder.itemView.setOnLongClickListener(View.OnLongClickListener {
    
                    if (selectedPosition == position) {
                        selectedPosition = -1
    //                    notifyItemChanged(position);
                    }
                    selectedPosition = position;
                    isSelect = true
                    notifyItemChanged(position);
mSelectedItems.add(selectedPosition)
                        items.get(position).id?.let { it1 -> deletList.add(it1)}
    
}

deletebutton.setOnClickListener {
               
                removeSelectedItems()
                selectedPosition = RecyclerView.NO_POSITION
                holder.itemView.setBackgroundColor(Color.parseColor("#00000000"));

            }
    }

}

Upvotes: 1

Views: 1257

Answers (2)

The gamers place
The gamers place

Reputation: 11

I too had this problem and had to solve it in a very specific way. The way i deleted the items was from within the adapter itself.

  1. First which is the most important is to store an instance of the recyler view within the adapter itself.
  2. Second you store the postions of your selected recyclerView items in an array list using holder.getAdapterPosition()
  3. Third you iterate through this list in a for loop and using the recycler view instance you created in the first step get the view holder for every position using recyclerView.findViewHolderForAdapterPosition()

One thing you need to note is you need to sort the list in step 2 in ascending order first and also the position you feed into the parameter for the 3rd step has to be reducued by the varaible you use for the for loop as the position in the adapter keeps changing.

Here I have provided my sample code I used the viewHolder to call a certain animation I wanted to call on delete its not necessary to use the viewHolder.

public class Your_Adapter extends RecyclerView.Adapter<Your_Adapter.ViewHolder>{
   private final RecyclerView recyclerView;
   private ArrayList<Integer> selected_Items_position = new ArrayList<>();

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

   holder.container.setOnClickListener(new View.OnClickListener() {
     selected_Items_position.add(holder.getAdapterPosition());
     
     // If you want to unselect the item you will have to implement your 
     // own logic also ull have to use something like selected_Items_position.remove(Integer.valueOf(holder.getAdapterPosition())); to remove the item from the selected list
   }
}

public void removeSelectedItems() {

   ViewHolder holder;
   Collections.sort(selected_Items_position);

   for (int i = 0; i< selected_Items_position.size(); i++) {

     holder = (ViewHolder) recyclerView.findViewHolderForAdapterPosition(selected_Items_position.get(i)-i);
     int actual_position = holder.getAdapterPosition();

     // Alternatively you could directly use 
    //int actual_position = selected_Items_position.get(i) - i;

    your_list_for_adpater.remove(actual_position);
    holder.item.startAnimation(remove); // Call animation on remove
    notifyItemRemoved(actual_position);
    }
   selected_BinItems_position.clear(); // dont forget this or ull get index out of bounds

}  
    
}

Upvotes: 0

Gobu CSG
Gobu CSG

Reputation: 691

Try this

Output

enter image description here

We can achieve multiple way

Declare a list in your adapter

private var mSelectedItems = arrayListOf<Int>()

On your view holder chosen index add to the list

holder.itemView.setOnLongClickListener(View.OnLongClickListener {
// Selected item index
mSelectedItems.add(layoutPosition)
}

Your delete function like this

//Single or multiple call this same function

fun removeSelectedItems(){
mSelectedItems.sortedDescending()
    mSelectedItems.forEach{itemIndex ->
        YOUR_ITEM_LIST.removeAt(itemIndex)
        notifyItemRemoved(itemIndex)
    }
    mSelectedItems.clear()
}

OR

fun removeSelectedItems(){
    YOUR_ITEM_LIST.removeAll(mSelectedItems)
    notifyDataSetChanged()
    mSelectedItems.clear()
}

OR

If you've bulk record go with Diffutil...

Here is the example https://developer.android.com/reference/androidx/recyclerview/widget/ListAdapter

You can use normal recyclerView adapter as well.

Upvotes: 2

Related Questions