mercredi 22 avril 2020

Handle checkbox state in RecyclerView which implements Filterable

I have a RecyclerView which implements Filterable that filters the list according to user input. RecyclerView item contains a CheckBox, when selecting the checkbox without filtered result the RecyclerView retains item's checkbox state as expected but if I select a checkbox and then filter the list by searching a name the checkbox state is lost. Same issue if I select a checkbox in a filtered list but then clear the filter the state is not retained.

I have gone through various SO answers like this, but the issue is when filtering the list along with checkbox state. I have tried using a boolean in the model class as well as maintaining a HashMap for selected Ids. Still not able to resolve the issue.

This is the adapter class that I am using:

public class MultiSelectUserAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements Filterable {

    private Context context;
    private List<SearchItem> rowItemList;
    private List<SearchItem> userListFiltered;
    private HashMap<String, String> selectedIdsMap;
    private LayoutInflater layoutInflater;
    private MultiSelectItemViewCallback listener;

    public MultiSelectUserAdapter(Context context,
                                  List<SearchItem> rowItemList,
                                  HashMap<String, String> selectedIdsMap,
                                  MultiSelectItemViewCallback listener) {
        this.context = context;
        this.rowItemList = rowItemList;
        this.userListFiltered = rowItemList;
        this.selectedIdsMap = selectedIdsMap;
        this.listener = listener;
    }

    public void updateHashMap(HashMap<String, String> selectedIds){
        this.selectedIdsMap = selectedIds;
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (layoutInflater == null) {
            layoutInflater = LayoutInflater.from(parent.getContext());
        }
        return new NotificationsViewHolder((ItemNotificationBinding)
                DataBindingUtil.inflate(layoutInflater, R.layout.item_notification,
                        parent, false));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
       ((NotificationsViewHolder) holder).bindMultiSelectItemViewHolder(context, userListFiltered.get(position),
               position, selectedIdsMap, listener);
    }

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

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                String charString = charSequence.toString();
                if (charString.isEmpty()) {
                    userListFiltered = rowItemList;
                } else {
                    List<SearchItem> filteredList = new ArrayList<>();
                    for (SearchItem row : rowItemList) {
                        if (row.getTitle().toLowerCase().contains(charString.toLowerCase())) {
                            filteredList.add(row);
                        }
                    }
                    userListFiltered = filteredList;
                }

                FilterResults filterResults = new FilterResults();
                filterResults.values = userListFiltered;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                userListFiltered = (ArrayList<SearchItem>) filterResults.values;
                notifyDataSetChanged();
            }
        };
    }
}

ViewHolder class:

public class NotificationsViewHolder extends RecyclerView.ViewHolder {

    private final ItemNotificationBinding binding;

    public NotificationsViewHolder(final ItemNotificationBinding itemBinding) {
        super(itemBinding.getRoot());
        this.binding = itemBinding;
    }

    public void bindMultiSelectItemViewHolder(Context context, final SearchItem rowItem, final int position,
                                              HashMap<String, String> selectedIdsMap, final MultiSelectItemViewCallback callback) {


        if (/*rowItem.isSelected()*/ selectedIdsMap.containsKey(rowItem.getRedirectionId())) {
            binding.checkbox.setChecked(true);
        }
        else {
            binding.checkbox.setChecked(false);
        }

        binding.checkbox.setOnCheckedChangeListener(
                new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        setCheckClick(rowItem, position, isChecked, callback);
                    }
                }
        );
    }

    private void setCheckClick(SearchItem rowItem, int position, boolean isChecked,
                               MultiSelectItemViewCallback callback){
        binding.checkbox.setChecked(isChecked);
        rowItem.setSelected(isChecked);
        callback.onMultiSelectItemClick(rowItem, position);
    }
}



Aucun commentaire:

Enregistrer un commentaire