package org.sugr.gearshift.ui; import android.support.v7.widget.RecyclerView; import android.util.SparseBooleanArray; import java.util.ArrayList; import java.util.List; public abstract class SelectableRecyclerViewAdapter<VH extends RecyclerView.ViewHolder, I> extends RecyclerView.Adapter<VH> { public List<I> itemData = new ArrayList<>(); protected SparseBooleanArray selectedItems = new SparseBooleanArray(); protected SelectableRecyclerViewAdapter() { registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { private static final int INSERT = 1; private static final int REMOVE = 2; private static final int MOVE = 3; @Override public void onItemRangeInserted(int positionStart, int itemCount) { shiftSelection(positionStart, -1, itemCount, INSERT); super.onItemRangeInserted(positionStart, itemCount); } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { shiftSelection(positionStart, -1, itemCount, REMOVE); super.onItemRangeRemoved(positionStart, itemCount); } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { shiftSelection(Math.min(fromPosition, toPosition), Math.max(fromPosition, toPosition), itemCount, MOVE); super.onItemRangeMoved(fromPosition, toPosition, itemCount); } private void shiftSelection(int start, int end, int count, int op) { List<Integer> deleted = new ArrayList<>(); List<Integer> added = new ArrayList<>(); for (int i = 0; i < selectedItems.size(); ++i) { int index = selectedItems.keyAt(i); if (index < start) { continue; } if (end != - 1 && index > end) { continue; } deleted.add(index); if (op == INSERT) { added.add(index + count); } else if (op == REMOVE) { if (index - count > 0) { added.add(index - count); } } else if (op == MOVE) { } } for (int index : deleted) { selectedItems.delete(index); } for (int index : added) { selectedItems.put(index, true); } } }); } public SparseBooleanArray getSelectedItemPositions() { return selectedItems.clone(); } public void setItemSelected(int position, boolean selected) { if (position == -1 || selected && !isItemSelectable(position)) { return; } if (selected) { selectedItems.put(position, true); } else { selectedItems.delete(position); } notifyItemChanged(position); } public void clearSelections() { SparseBooleanArray selected = selectedItems.clone(); for (int i = 0; i < selected.size(); ++i) { int index = selected.keyAt(i); setItemSelected(index, false); } } public int getSelectedItemCount() { return selectedItems.size(); } public List<I> getSelectedItems() { List<I> items = new ArrayList<>(selectedItems.size()); for (int i = 0; i < selectedItems.size(); i++) { int index = selectedItems.keyAt(i); if (itemData.size() > index) { items.add(itemData.get(index)); } } return items; } public abstract boolean isItemSelectable(int position); @Override public void onBindViewHolder(VH holder, int position) { holder.itemView.setActivated( isItemSelectable(position) && selectedItems.get(position, false)); } @Override public int getItemCount() { return this.itemData.size(); } }