use of eu.davidea.flexibleadapter.items.IExpandable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method toggleSelection.
/**
* {@inheritDoc}
*
* @param position position of the item to toggle the selection status for.
* @since 5.0.0-b1
*/
//TODO: Review the logic of selection coherence
@Override
public void toggleSelection(@IntRange(from = 0) int position) {
T item = getItem(position);
// Allow selection only for selectable items
if (item != null && item.isSelectable()) {
IExpandable parent = getExpandableOf(item);
boolean hasParent = parent != null;
if ((isExpandable(item) || !hasParent) && !childSelected) {
// Allow selection of Parent if no Child has been previously selected
parentSelected = true;
if (hasParent)
mSelectedLevel = parent.getExpansionLevel();
super.toggleSelection(position);
} else if (!parentSelected && hasParent && parent.getExpansionLevel() + 1 == mSelectedLevel || mSelectedLevel == -1) {
// Allow selection of Child of same level and if no Parent has been previously selected
childSelected = true;
mSelectedLevel = parent.getExpansionLevel() + 1;
super.toggleSelection(position);
}
}
// Reset flags if necessary, just to be sure
if (getSelectedItemCount() == 0) {
mSelectedLevel = -1;
parentSelected = childSelected = false;
}
}
use of eu.davidea.flexibleadapter.items.IExpandable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method expand.
/**
* Convenience method to initially expand a single item.
* <p><b>Note:</b> Must be used in combination with adding new items that require to be
* initially expanded.</p>
* <b>WARNING!</b>
* <br/>Expanded status is ignored if {@code init = true}: it will always attempt to expand
* the item: If subItems are already visible <u>and</u> the new item has status expanded, the
* subItems will appear duplicated(!) and the automatic smooth scroll will be skipped!
*
* @param position the position of the item to expand
* @param init true to initially expand item
* @param notifyParent true to notify the parent with {@link Payload#EXPANDED}
* @return the number of subItems expanded
* @since 5.0.0-rc2
*/
private int expand(int position, boolean expandAll, boolean init, boolean notifyParent) {
T item = getItem(position);
if (!isExpandable(item))
return 0;
IExpandable expandable = (IExpandable) item;
if (!hasSubItems(expandable)) {
//clear the expanded flag
expandable.setExpanded(false);
if (DEBUG)
Log.w(TAG, "No subItems to Expand on position " + position + " expanded " + expandable.isExpanded());
return 0;
}
if (DEBUG && !init && !expandAll) {
Log.v(TAG, "Request to Expand on position=" + position + " expanded=" + expandable.isExpanded() + " anyParentSelected=" + parentSelected);
}
int subItemsCount = 0;
if (init || !expandable.isExpanded() && (!parentSelected || expandable.getExpansionLevel() <= mSelectedLevel)) {
// Fetch again the new position after collapsing all!!
if (collapseOnExpand && !expandAll && collapseAll(mMinCollapsibleLevel) > 0) {
position = getGlobalPositionOf(item);
}
// Every time an expansion is requested, subItems must be taken from the
// original Object and without the subItems marked hidden (removed)
List<T> subItems = getExpandableList(expandable);
mItems.addAll(position + 1, subItems);
subItemsCount = subItems.size();
// Save expanded state
expandable.setExpanded(true);
// children as possible
if (!init && scrollOnExpand && !expandAll) {
autoScrollWithDelay(position, subItemsCount, 150L);
}
// Expand!
if (notifyParent)
notifyItemChanged(position, Payload.EXPANDED);
notifyItemRangeInserted(position + 1, subItemsCount);
// Show also the headers of the subItems
if (!init && headersShown) {
int count = 0;
for (T subItem : subItems) {
if (showHeaderOf(position + (++count), subItem, false))
count++;
}
}
// Expandable as a Scrollable Header/Footer
if (!expandSHF(mScrollableHeaders, expandable))
expandSHF(mScrollableFooters, expandable);
if (DEBUG) {
Log.v(TAG, (init ? "Initially expanded " : "Expanded ") + subItemsCount + " subItems on position=" + position);
}
}
return subItemsCount;
}
use of eu.davidea.flexibleadapter.items.IExpandable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method createRestoreItemInfo.
/**
* @param position the position of the item to retain.
* @param item the deleted item
* @since 5.0.0-b1
*/
private void createRestoreItemInfo(int position, T item, @Nullable Object payload) {
// Collapse Parent before removal if it is expanded!
if (isExpanded(item))
collapse(position);
item.setHidden(true);
// Get the reference of the previous item (getItem returns null if outOfBounds)
// If null, it will be restored at position = 0
T refItem = getItem(position - 1);
if (refItem != null) {
// Check if the refItem is a child of an Expanded parent, take the parent!
IExpandable expandable = getExpandableOf(refItem);
if (expandable != null)
refItem = (T) expandable;
}
mRestoreList.add(new RestoreInfo(refItem, item, payload));
if (DEBUG)
Log.v(TAG, "Recycled Parent " + mRestoreList.get(mRestoreList.size() - 1) + " on position=" + position);
}
use of eu.davidea.flexibleadapter.items.IExpandable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method addSubItems.
/**
* Convenience method of {@link #addSubItems(int, int, IExpandable, List, boolean, Object)}.
* <br/>Optionally you can pass any payload to notify the parent about the change and optimize
* the view binding.
*
* @param parentPosition position of the expandable item that shall contain the subItems
* @param subPosition the start position in the parent where the new items shall be inserted
* @param items the list of the subItems to add
* @param expandParent true to initially expand the parent (if needed) and after to add
* the subItems, false to simply add the subItems to the parent
* @param payload any non-null user object to notify the parent (the payload will be
* therefore passed to the bind method of the parent ViewHolder),
* pass null to <u>not</u> notify the parent
* @return true if the internal list was successfully modified, false otherwise
* @see #addSubItems(int, int, IExpandable, List, boolean, Object)
* @since 5.0.0-b1
*/
public boolean addSubItems(@IntRange(from = 0) int parentPosition, @IntRange(from = 0) int subPosition, @NonNull List<T> items, boolean expandParent, @Nullable Object payload) {
T parent = getItem(parentPosition);
if (isExpandable(parent)) {
IExpandable expandable = (IExpandable) parent;
return addSubItems(parentPosition, subPosition, expandable, items, expandParent, payload);
}
Log.e(TAG, "Provided parentPosition doesn't belong to an Expandable item!");
return false;
}
use of eu.davidea.flexibleadapter.items.IExpandable in project FlexibleAdapter by davideas.
the class FlexibleAdapter method filterExpandableObject.
/**
* This method is a wrapper filter for expandable items.<br/>
* It performs filtering on the subItems returning true, if the any child should be in the
* filtered collection.
* <p>If the provided item is not an expandable it will be filtered as usual by
* {@link #filterObject(T, String)}.</p>
*
* @param item the object with subItems to be inspected
* @return true, if the object should be in the filteredResult, false otherwise
* @since 5.0.0-b1
*/
private boolean filterExpandableObject(T item) {
// Reset expansion flag
boolean filtered = false;
if (isExpandable(item)) {
IExpandable expandable = (IExpandable) item;
// Save which expandable was originally expanded before filtering it out
if (expandable.isExpanded()) {
if (mExpandedFilterFlags == null)
mExpandedFilterFlags = new HashSet<>();
mExpandedFilterFlags.add(expandable);
}
expandable.setExpanded(false);
// Children scan filter
for (T subItem : getCurrentChildren(expandable)) {
// Reuse normal filter for Children
subItem.setHidden(!filterObject(subItem, getSearchText()));
if (!filtered && !subItem.isHidden()) {
filtered = true;
}
}
// Expand if filter found text in subItems
expandable.setExpanded(filtered);
}
// if not filtered already, fallback to Normal filter
return filtered || filterObject(item, getSearchText());
}
Aggregations