@Override public boolean areItemsTheSame(Item oldItem, Item newItem) { return oldItem.getIdentifier() == newItem.getIdentifier(); }
@Override public boolean apply(@NonNull IAdapter<Item> lastParentAdapter, int lastParentPosition, Item item, int position) { if (item.isSelected()) { items.add(item); } return false; } }, false);
/** * select's a provided item, this won't notify the adapter * * @param item the item to select * @param considerSelectableFlag true if the select method should not select an item if its not selectable */ public void select(Item item, boolean considerSelectableFlag) { if (considerSelectableFlag && !item.isSelectable()) { return; } item.withSetSelected(true); if (mSelectionListener != null) { mSelectionListener.onSelectionChanged(item, true); } }
/** * the onCreateViewHolder is managed by the FastAdapter so forward this correctly * * @param parent * @param viewType * @return */ @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //TODO OPTIMIZE for (Item item : mItems) { if (item.getType() == viewType) { return item.getViewHolder(parent); } } return mAdapter.onCreateViewHolder(parent, viewType); }
@Override public boolean apply(@NonNull IAdapter lastParentAdapter, int lastParentPosition, @NonNull IItem item, int position) { if (item.getIdentifier() == identifier) { if (position != -1) { SelectExtension extension = (SelectExtension) adapter.getExtension(SelectExtension.class); if (extension != null) { if (select) { extension.select(position); } else { extension.deselect(position); } } } else { item.withSetSelected(select); } return true; } return false; } }, true);
if (!item.isSelectable()) { return; if (item.isSelected() && !mAllowDeselection) { return; boolean selected = item.isSelected(); item.withSetSelected(!selected); view.setSelected(!selected);
/** * internal method to find all selections from subItems and sub sub items so we can save those inside our savedInstanceState * * @param item the parent item * @param selections the ArrayList which will be stored in the savedInstanceState */ public static <Item extends IItem> void findSubItemSelections(Item item, List<String> selections) { if (item instanceof IExpandable && !((IExpandable) item).isExpanded() && ((IExpandable) item).getSubItems() != null) { List<Item> subItems = (List<Item>) ((IExpandable<Item, ?>) item).getSubItems(); for (int i = 0, size = subItems.size(); i < size; i++) { Item subItem = subItems.get(i); String id = String.valueOf(subItem.getIdentifier()); if (subItem.isSelected()) { selections.add(id); } findSubItemSelections(subItem, selections); } } }
/** * implements the basic behavior of a CAB and multi select behavior, * including logics if the clicked item is collapsible * * @param act the current Activity * @param item the current item * @return null if nothing was done, or a boolean to inform if the event was consumed */ public Boolean onClick(AppCompatActivity act, IItem item) { //if we are current in CAB mode, and we remove the last selection, we want to finish the actionMode if (mActionMode != null && (mSelectExtension.getSelectedItems().size() == 1) && item.isSelected()) { mActionMode.finish(); mSelectExtension.deselect(); return true; } if (mActionMode != null) { // calculate the selection count for the action mode // because current selection is not reflecting the future state yet! int selected = mSelectExtension.getSelectedItems().size(); if (item.isSelected()) selected--; else if (item.isSelectable()) selected++; checkActionMode(act, selected); } return null; }
@Override public boolean apply(@NonNull IAdapter lastParentAdapter, int lastParentPosition, @NonNull IItem item, int position) { if (position != -1) { SelectExtension extension = (SelectExtension) adapter.getExtension(SelectExtension.class); if (extension != null) { extension.deselect(position); } } else { item.withSetSelected(false); } return true; } }, false);
/** * implements the basic behavior of a CAB and multi select behavior onLongClick * * @param act the current Activity * @param position the position of the clicked item * @return the initialized ActionMode or null if nothing was done */ public ActionMode onLongClick(AppCompatActivity act, int position) { if (mActionMode == null && mFastAdapter.getItem(position).isSelectable()) { //may check if actionMode is already displayed mActionMode = act.startSupportActionMode(mInternalCallback); //we have to select this on our own as we will consume the event mSelectExtension.select(position); // update title checkActionMode(act, 1); //we consume this event so the normal onClick isn't called anymore return mActionMode; } return mActionMode; }
/** * is called in onBindViewHolder to bind the data on the ViewHolder * * @param viewHolder the viewHolder for the type at this position * @param position the position of this viewHolder * @param payloads the payloads provided by the adapter */ @Override public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position, List<Object> payloads) { Object tag = viewHolder.itemView.getTag(R.id.fastadapter_item_adapter); if (tag instanceof FastAdapter) { FastAdapter fastAdapter = ((FastAdapter) tag); IItem item = fastAdapter.getItem(position); if (item != null) { item.bindView(viewHolder, payloads); if (viewHolder instanceof FastAdapter.ViewHolder) { ((FastAdapter.ViewHolder) viewHolder).bindView(item, payloads); } //set the R.id.fastadapter_item tag of this item to the item object (can be used when retrieving the view) viewHolder.itemView.setTag(R.id.fastadapter_item, item); } } }
/** * is called inside the onCreateViewHolder method and creates the viewHolder based on the provided viewTyp * * @param parent the parent which will host the View * @param viewType the type of the ViewHolder we want to create * @return the generated ViewHolder based on the given viewType */ @Override public RecyclerView.ViewHolder onPreCreateViewHolder(FastAdapter<Item> fastAdapter, ViewGroup parent, int viewType) { return fastAdapter.getTypeInstance(viewType).getViewHolder(parent); }
/** * internal method to restore the selection state of subItems * * @param item the parent item * @param selectedItems the list of selectedItems from the savedInstanceState */ public static <Item extends IItem> void restoreSubItemSelectionStatesForAlternativeStateManagement(Item item, List<String> selectedItems) { if (item instanceof IExpandable && !((IExpandable) item).isExpanded() && ((IExpandable) item).getSubItems() != null) { List<Item> subItems = (List<Item>) ((IExpandable<Item, ?>) item).getSubItems(); for (int i = 0, size = subItems.size(); i < size; i++) { Item subItem = subItems.get(i); String id = String.valueOf(subItem.getIdentifier()); if (selectedItems != null && selectedItems.contains(id)) { subItem.withSetSelected(true); } restoreSubItemSelectionStatesForAlternativeStateManagement(subItem, selectedItems); } } }
/** * deselects an item and removes its position in the selections list * also takes an iterator to remove items from the map * * @param item the item to deselected * @param position the global position (or < 0 if the item is not displayed) * @param entries the iterator which is used to deselect all */ public void deselect(Item item, int position, @Nullable Iterator<Integer> entries) { item.withSetSelected(false); if (entries != null) { entries.remove(); } if (position >= 0) { mFastAdapter.notifyItemChanged(position); } if (mSelectionListener != null) { mSelectionListener.onSelectionChanged(item, false); } }
/** * finds the int ItemViewType from the IItem which exists at the given position * * @param position the global position * @return the viewType for this position */ @Override public int getItemViewType(int position) { return getItem(position).getType(); }
/** * will take care to save the long pressed index * or to select all items in the range between the current long pressed item and the last long pressed item * * @param index the index of the long pressed item * @param selectItem true, if the item at the index should be selected, false if this was already done outside of this helper or is not desired * @return true, if the long press was handled */ public boolean onLongClick(int index, boolean selectItem) { if (mLastLongPressIndex == null) { // we only consider long presses on not selected items if (mFastAdapter.getAdapterItem(index).isSelectable()) { mLastLongPressIndex = index; // we select this item as well if (selectItem) mFastAdapter.select(index); if (mActionModeHelper != null) mActionModeHelper.checkActionMode(null); // works with null as well, as the ActionMode is active for sure! return true; } } else if (mLastLongPressIndex != index) { // select all items in the range between the two long clicks selectRange(mLastLongPressIndex, index, true); // reset the index mLastLongPressIndex = null; } return false; }
/** * the onBindViewHolder is managed by the FastAdapter so forward this correctly * * @param holder * @param position */ @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List payloads) { if (shouldInsertItemAtPosition(position)) { getItem(position).bindView(holder, payloads); } else { mAdapter.onBindViewHolder(holder, position - itemInsertedBeforeCount(position), payloads); } }
@Override public boolean apply(@NonNull IAdapter lastParentAdapter, int lastParentPosition, @NonNull IItem item, int position) { return item.getIdentifier() == identifier; } }, true);
private static void updateSelectedItemsWithCollapsed(Set<IItem> selected, List<IItem> items) { int length = items.size(); for (int i = 0; i < length; i++) { if (items.get(i).isSelected()) { selected.add(items.get(i)); } if (items.get(i) instanceof IExpandable && ((IExpandable) items.get(i)).getSubItems() != null) { updateSelectedItemsWithCollapsed(selected, ((IExpandable) items.get(i)).getSubItems()); } } }