0

Hello I am trying to implement multi select in recycler view android for showing an icon when clicked on that particular view, I have tried the below code and is working fine for that particular position, however there are other several views that too are getting updated, so please check and let me know what am I missing

Here is my adapter code:

public class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{

Context context;
ArrayList<String> alContactName, alContactEmail, alContactNumber;
ArrayList<Boolean> alFromLinkedIn;
int mergeFlag=0;
private static SparseBooleanArray selectedItems;
ArrayList<Integer> alSelectedPositions;

public ContactsAdapter(Context context, ArrayList<String> alContactName, ArrayList<String> alContactEmail, ArrayList<String> alContactNumber, ArrayList<Boolean> alisFromLinkedIn) {
    //Include one more variable for checking type i.e linked in or normal contact
    super();
    this.context = context;
    this.alContactName = alContactName;
    this.alContactEmail = alContactEmail;
    this.alContactNumber = alContactNumber;
    this.alFromLinkedIn = alisFromLinkedIn;
    alSelectedPositions=new ArrayList<>();
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater inflater = LayoutInflater.from(context);
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_merge_contact, parent, false);
    return new ContactsHolder(view);
}

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
    try {
        ((ContactsHolder) holder).relMain.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                alSelectedPositions.add(position);
                notifyDataSetChanged();
            }
        });
      if(alSelectedPositions.get(position)==position){
            ((ContactsHolder) holder).imgMerge.setVisibility(View.VISIBLE);
        }
        else {
            ((ContactsHolder) holder).imgMerge.setVisibility(View.GONE);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
Shyamal
  • 21
  • 1
  • 6
  • Multi selection is part of [this tutorial](https://www.androidhive.info/2017/02/android-creating-gmail-like-inbox-using-recyclerview/) that i suggest you review. – Burak Cakir Apr 24 '18 at 07:43
  • For Kotlin users, the following article might be useful [How to delete multiple records from Firestore using RecyclerView multi-selection?](https://medium.com/firebase-tips-tricks/how-to-delete-multiple-records-from-firestore-using-recyclerview-multi-selection-96108e4c6166). – Alex Mamo Jan 04 '21 at 17:11

4 Answers4

0

You've to do some specific things:

  • Initialize an int type array (type can be different) and assign 0 value to all it's elements.

    int[] selectedPos = null;
    public ContactsAdapter(Context context, ArrayList<String> alContactName, ArrayList<String> alContactEmail, ArrayList<String> alContactNumber, ArrayList<Boolean> alisFromLinkedIn) {
        //Include one more variable for checking type i.e linked in or normal contact
        super();
        this.context = context;
        this.alContactName = alContactName;
        this.alContactEmail = alContactEmail;
        this.alContactNumber = alContactNumber;
        this.alFromLinkedIn = alisFromLinkedIn;
        alSelectedPositions=new ArrayList<>();
    
        for(int i = 0 ; i < alContactName.size() ; i++)
            selectedPos[i] = 0;
    }
    
  • Store the selected positions in selectedPos.

  • Then, check if the position is selected and set visibility accordingly:

In onBindViewHolder() add the following code:

public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
    try {
        ((ContactsHolder) holder).relMain.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            selectedPos[position] = 1;
            notifyDataSetChanged();
        }
    });

    } catch (Exception e) {
        e.printStackTrace();
    }

    // Checking if the position was selected
    if(selectedPos[position] == 1)
        ((ContactsHolder) holder).imgMerge.setVisibility(View.VISIBLE);
    else
        ((ContactsHolder) holder).imgMerge.setVisibility(View.GONE);

}
tahsinRupam
  • 6,325
  • 1
  • 18
  • 34
0

Recently I had to implement a multi select RecyclerView, below I attached a simplified code snippet for a clean way to implement multi-select feature in RecyclerView:

public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemHolder> implements IMultiSelectableList<Item> {

    boolean selectionMode = false;
    HashSet<Item> selectedItems;
    ArrayList<Item> mItems;

    public ItemAdapter(ArrayList<Item> Items) {
        super();

        selectedItems = new HashSet<>();
        mItems = Items;
    }

    public void enterSelectionModeWithItem(int selectedItemPosition){
        if(selectedItemPosition >= 0 && selectedItemPosition < mItems.size())
            selectedItems.add(mItems.get(selectedItemPosition));

        selectionMode = true;
        notifyDataSetChanged();
    }

    public void clearSelectionMode() {
        selectionMode = false;
        selectedItems.clear();
        notifyDataSetChanged();
    }

    public class ItemHolder extends RecyclerView.ViewHolder{

        ImageView mImage;

        public ItemHolder(View itemView) {
            super(itemView);
            mImage = itemView.findViewById(R.id.image);

            itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    if(!selectionMode){
                        int selectedPosition = getAdapterPosition();
                        Item selectedItem = mItems.get(selectedPosition);
                        enterSelectionModeWithItem(selectedItem);
                        return true;
                    }
                    return false;
                }
            });

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    int selectedPosition = getAdapterPosition();
                    Item selectedItem = mItems.get(selectedPosition);

                    //Capture Clicks in Selection Mode
                    if(selectionMode){
                        if(selectedItems.contains(selectedItem)){
                            selectedItems.remove(selectedItem);
                            mImage.setImageResource(R.drawable.ic_checkbox_blank_circle_outline_grey600_48dp);
                        } else {
                            selectedItems.add(selectedItem);
                            mImage.setImageResource(R.drawable.ic_checkbox_marked_circle_grey600_48dp);
                        }
                    }
                }
            });
        }

        public void setupView(Item item){
            if(selectionMode){
                if(selectedItems.contains(item)){
                    mImage.setImageResource(R.drawable.ic_checkbox_marked_circle_grey600_48dp);
                } else {
                    mImage.setImageResource(R.drawable.ic_checkbox_blank_circle_outline_grey600_48dp);
                }
        }
    }

    @Override
    public ItemAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_item, parent, false);
        return new ItemHolder(view);
    }

    @Override
    public void onBindViewHolder(ItemAdapter.ItemHolder holder, int position) {
        holder.setupView(mItems.get(position));
    }

    @Override
    public int getItemCount() {
        return mItems != null ? mItems.size() : 0;
    }
}

, I use an image to show selection like Gmail app but feel free to use whatever works for you (background color, font style, etc).

P.S: I designed a callback interface for a simple selection interactions, if it helps I can attach it too! Cheers!

Keivan Esbati
  • 3,376
  • 1
  • 22
  • 36
0

check updated code. I have modified the @tahsinRupam code.

 @Override
        public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
            try {
                ((ContactsHolder) holder).relMain.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if(alSelectedPositions.size>0)
                         {
                          for(int i=0;i<a1SelectedPositions.size;i++)
                          {
                           //if you want to cleasr previous details of array
                           if(a1SelectedPositions.contains(position))
                             alSelectedPositions.remove(position);
                           else
                            alSelectedPositions.add(position);
                         }
                       }
               else
               {
                 alSelectedPositions.add(position);
                  notifyDataSetChanged();
                    }
                });

//update the position on scroll     
              for(int i=0;i<a1SelectedPositions.size;i++)
               {
                 if(alSelectedPositions.get(i)==position){
                  ((ContactsHolder)holder).imgMerge.setVisibility(View.VISIBLE);
                }
                else {
                    ((ContactsHolder) holder).imgMerge.setVisibility(View.GONE);
                }
          }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
Praveen Rawat
  • 314
  • 1
  • 3
  • 14
0

I have resolved my issue here is the code if it could help someone:

@Override
    public ContactsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_merge_contact, parent, false);
        final ContactsHolder holder = new ContactsHolder(view);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (holder.getAdapterPosition() != RecyclerView.NO_POSITION) {
                    mSelectedItemPosition = holder.getAdapterPosition();
                    //notifyItemChanged(holder.getAdapterPosition());
                    notifyDataSetChanged();
                }
            }
        });
        return holder;
    }

@Override
    public void onBindViewHolder(ContactsHolder holder, int position) {
        try {
            if (mSelectedItemPosition == position) {
                if (mergeFlag != 1) {
                    holder.imgMerge.setVisibility(View.VISIBLE);
                    mergeFlag = 1;
                    selectdParentId = contactsModels.get(position).alContactIdList;
                } else{
                    //holder.relDone.setVisibility(View.GONE);
                    if (!selectdParentId.equals(contactsModels.get(position).alContactIdList)) {
                        holder.relDone.setVisibility(View.VISIBLE);
                        alChildId.add(contactsModels.get(position).alContactIdList);

                    } else {
                        holder.imgMerge.setVisibility(View.VISIBLE);
                    }
                }
            } else {
                holder.imgMerge.setVisibility(View.GONE);
                holder.relDone.setVisibility(View.GONE);
            }
}
Shyamal
  • 21
  • 1
  • 6