Search in sources :

Example 6 with ISectionable

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);
    }
}
Also used : FlexibleAdapter(eu.davidea.flexibleadapter.FlexibleAdapter) ISectionable(eu.davidea.flexibleadapter.items.ISectionable)

Example 7 with ISectionable

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));
}
Also used : IHeader(eu.davidea.flexibleadapter.items.IHeader) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) ISectionable(eu.davidea.flexibleadapter.items.ISectionable) SuppressLint(android.annotation.SuppressLint)

Example 8 with ISectionable

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);
}
Also used : ISectionable(eu.davidea.flexibleadapter.items.ISectionable) SuppressLint(android.annotation.SuppressLint)

Example 9 with ISectionable

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;
}
Also used : ISectionable(eu.davidea.flexibleadapter.items.ISectionable)

Example 10 with ISectionable

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);
            }
        }
    }
}
Also used : IHeader(eu.davidea.flexibleadapter.items.IHeader) ISectionable(eu.davidea.flexibleadapter.items.ISectionable) SuppressLint(android.annotation.SuppressLint)

Aggregations

ISectionable (eu.davidea.flexibleadapter.items.ISectionable)11 SuppressLint (android.annotation.SuppressLint)7 IHeader (eu.davidea.flexibleadapter.items.IHeader)6 ArrayList (java.util.ArrayList)2 NonNull (android.support.annotation.NonNull)1 FlexibleAdapter (eu.davidea.flexibleadapter.FlexibleAdapter)1 IExpandable (eu.davidea.flexibleadapter.items.IExpandable)1 ExpandableHeaderItem (eu.davidea.samples.flexibleadapter.items.ExpandableHeaderItem)1 List (java.util.List)1