use of eu.davidea.flexibleadapter.items.ISectionable in project FlexibleAdapter by davideas.
the class DividerItemDecoration method getItemOffsets.
/**
* @since 5.0.0-b4
*/
@SuppressWarnings({ "ConstantConditions", "unchecked", "SuspiciousNameCombination" })
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView recyclerView, RecyclerView.State state) {
int offset = (mDivider != null && withOffset ? mDivider.getIntrinsicHeight() : 0);
if (mSectionOffset > 0 && recyclerView.getAdapter() instanceof FlexibleAdapter) {
FlexibleAdapter flexibleAdapter = (FlexibleAdapter) recyclerView.getAdapter();
int position = recyclerView.getChildAdapterPosition(view);
//Only ISectionable items can finish with a gap and only if next item is a IHeader item
if (flexibleAdapter.getItem(position) instanceof ISectionable && (flexibleAdapter.isHeader(flexibleAdapter.getItem(position + 1)) || position >= recyclerView.getAdapter().getItemCount() - 1)) {
offset += mSectionOffset;
}
}
if (Utils.getOrientation(recyclerView.getLayoutManager()) == RecyclerView.VERTICAL) {
outRect.set(0, 0, 0, offset);
} else {
outRect.set(0, 0, offset, 0);
}
}
use of eu.davidea.flexibleadapter.items.ISectionable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method calculatePositionFor.
/**
* New method to extract the new position where the item should lay.
* <p><b>Note: </b>The {@code Comparator} object should be customized to support <u>all</u>
* types of items this Adapter is managing or a {@code ClassCastException} will be raised.</p>
* If the {@code Comparator} is {@code null} the returned position is 0 (first position).
*
* @param item the item to evaluate the insertion
* @param comparator the Comparator object with the logic to sort the list
* @return the position resulted from sorting with the provided Comparator
* @since 5.0.0-b7
*/
public int calculatePositionFor(@NonNull Object item, @Nullable Comparator comparator) {
// There's nothing to compare
if (comparator == null)
return 0;
// Header is visible
if (item instanceof ISectionable) {
IHeader header = ((ISectionable) item).getHeader();
if (header != null && !header.isHidden()) {
List sortedList = getSectionItems(header);
sortedList.add(item);
Collections.sort(sortedList, comparator);
int itemPosition = mItems.indexOf(item);
int headerPosition = getGlobalPositionOf(header);
// #143 - calculatePositionFor() missing a +1 when addItem (fixed by condition: itemPosition != -1)
// fix represents the situation when item is before the target position (used in moveItem)
int fix = itemPosition != -1 && itemPosition < headerPosition ? 0 : 1;
int result = headerPosition + sortedList.indexOf(item) + fix;
if (DEBUG) {
Log.v(TAG, "Calculated finalPosition=" + result + " sectionPosition=" + headerPosition + " relativePosition=" + sortedList.indexOf(item) + " fix=" + fix);
}
return result;
}
}
// All other cases
List sortedList = new ArrayList(mItems);
if (!sortedList.contains(item))
sortedList.add(item);
Collections.sort(sortedList, comparator);
if (DEBUG)
Log.v(TAG, "Calculated position " + Math.max(0, sortedList.indexOf(item)) + " for item=" + item);
return Math.max(0, sortedList.indexOf(item));
}
use of eu.davidea.flexibleadapter.items.ISectionable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method addItemToSection.
/**
* Adds a new item in a section when the relative position is <b>unknown</b>.
* <p>The header can be a {@code IExpandable} type or {@code IHeader} type.</p>
* The Comparator object must support <u>all</u> the item types this Adapter is displaying or
* a ClassCastException will be raised.
*
* @param sectionable the item to add
* @param header the section receiving the new item
* @param comparator the criteria to sort the sectionItems used to extract the correct position
* of the new item in the section
* @return the calculated final position for the new item
* @see #addItemToSection(ISectionable, IHeader, int)
* @since 5.0.0-b6
*/
public int addItemToSection(@NonNull ISectionable sectionable, @NonNull IHeader header, @NonNull Comparator comparator) {
int index;
if (header != null && !header.isHidden()) {
List<ISectionable> sectionItems = getSectionItems(header);
sectionItems.add(sectionable);
//Sort the list for new position
Collections.sort(sectionItems, comparator);
//Get the new position
index = sectionItems.indexOf(sectionable);
} else {
index = calculatePositionFor(sectionable, comparator);
}
return addItemToSection(sectionable, header, index);
}
use of eu.davidea.flexibleadapter.items.ISectionable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method linkHeaderTo.
/**
* Internal method to link the header to the new item.
* <p>Used by the Adapter during the Remove/Restore/Move operations.</p>
* The new item looses the previous header, and if the old header is not shared,
* old header is added to the orphan list.
*
* @param item the item that holds the header
* @param header the header item
* @param payload any non-null user object to notify the header and the item (the payload
* will be therefore passed to the bind method of the items ViewHolder),
* pass null to <u>not</u> notify the header and item
* @since 5.0.0-b6
*/
private boolean linkHeaderTo(@NonNull T item, @NonNull IHeader header, @Nullable Object payload) {
boolean linked = false;
if (item != null && item instanceof ISectionable) {
ISectionable sectionable = (ISectionable) item;
// Unlink header only if different
if (sectionable.getHeader() != null && !sectionable.getHeader().equals(header)) {
unlinkHeaderFrom((T) sectionable, Payload.UNLINK);
}
if (sectionable.getHeader() == null && header != null) {
if (DEBUG)
Log.v(TAG, "Link header " + header + " to " + sectionable);
//TODO: try-catch for when sectionable item has a different header class signature, if so, they just can't accept that header!
sectionable.setHeader(header);
linked = true;
removeFromOrphanList(header);
// Notify items
if (payload != null) {
if (!header.isHidden())
notifyItemChanged(getGlobalPositionOf(header), payload);
if (!item.isHidden())
notifyItemChanged(getGlobalPositionOf(item), payload);
}
}
} else {
addToOrphanListIfNeeded(header, getGlobalPositionOf(item), 1);
notifyItemChanged(getGlobalPositionOf(header), payload);
}
return linked;
}
use of eu.davidea.flexibleadapter.items.ISectionable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method swapItems.
/**
* Swaps the elements of list at indices fromPosition and toPosition and notify the change.
* <p>Selection of swiped elements is automatically updated.</p>
*
* @param fromPosition previous position of the item.
* @param toPosition new position of the item.
* @since 5.0.0-b7
*/
public void swapItems(List<T> list, int fromPosition, int toPosition) {
if (fromPosition < 0 || fromPosition >= getItemCount() || toPosition < 0 || toPosition >= getItemCount()) {
return;
}
if (DEBUG) {
Log.v(TAG, "swapItems from=" + fromPosition + " [selected? " + isSelected(fromPosition) + "] to=" + toPosition + " [selected? " + isSelected(toPosition) + "]");
}
// Collapse expandable before swapping (otherwise items are mixed badly)
if (fromPosition < toPosition && isExpandable(getItem(fromPosition)) && isExpanded(toPosition)) {
collapse(toPosition);
}
// Perform item swap (for all LayoutManagers)
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
if (DEBUG)
Log.v(TAG, "swapItems from=" + i + " to=" + (i + 1));
Collections.swap(mItems, i, i + 1);
swapSelection(i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
if (DEBUG)
Log.v(TAG, "swapItems from=" + i + " to=" + (i - 1));
Collections.swap(mItems, i, i - 1);
swapSelection(i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
// Header swap linkage
if (headersShown) {
// Situation AFTER items have been swapped, items are inverted!
T fromItem = getItem(toPosition);
T toItem = getItem(fromPosition);
int oldPosition, newPosition;
if (toItem instanceof IHeader && fromItem instanceof IHeader) {
if (fromPosition < toPosition) {
// Dragging down fromHeader
// Auto-linkage all section-items with new header
IHeader header = (IHeader) fromItem;
List<ISectionable> items = getSectionItems(header);
for (ISectionable sectionable : items) {
linkHeaderTo((T) sectionable, header, Payload.LINK);
}
} else {
// Dragging up fromHeader
// Auto-linkage all section-items with new header
IHeader header = (IHeader) toItem;
List<ISectionable> items = getSectionItems(header);
for (ISectionable sectionable : items) {
linkHeaderTo((T) sectionable, header, Payload.LINK);
}
}
} else if (toItem instanceof IHeader) {
// A Header is being swapped up
// Else a Header is being swapped down
oldPosition = fromPosition < toPosition ? toPosition + 1 : toPosition;
newPosition = fromPosition < toPosition ? toPosition : fromPosition + 1;
// Swap header linkage
linkHeaderTo(getItem(oldPosition), getSectionHeader(oldPosition), Payload.LINK);
linkHeaderTo(getItem(newPosition), (IHeader) toItem, Payload.LINK);
} else if (fromItem instanceof IHeader) {
// A Header is being dragged down
// Else a Header is being dragged up
oldPosition = fromPosition < toPosition ? fromPosition : fromPosition + 1;
newPosition = fromPosition < toPosition ? toPosition + 1 : fromPosition;
// Swap header linkage
linkHeaderTo(getItem(oldPosition), getSectionHeader(oldPosition), Payload.LINK);
linkHeaderTo(getItem(newPosition), (IHeader) fromItem, Payload.LINK);
} else {
// A Header receives the toItem
// Else a Header receives the fromItem
oldPosition = fromPosition < toPosition ? toPosition : fromPosition;
newPosition = fromPosition < toPosition ? fromPosition : toPosition;
// Swap header linkage
T oldItem = getItem(oldPosition);
IHeader header = getHeaderOf(oldItem);
if (header != null) {
IHeader oldHeader = getSectionHeader(oldPosition);
if (oldHeader != null && !oldHeader.equals(header)) {
linkHeaderTo(oldItem, oldHeader, Payload.LINK);
}
linkHeaderTo(getItem(newPosition), header, Payload.LINK);
}
}
}
}
Aggregations