diff --git a/flexible-adapter/src/main/java/eu/davidea/flexibleadapter/FlexibleAdapter.java b/flexible-adapter/src/main/java/eu/davidea/flexibleadapter/FlexibleAdapter.java index 2b9021db..a2d093c7 100644 --- a/flexible-adapter/src/main/java/eu/davidea/flexibleadapter/FlexibleAdapter.java +++ b/flexible-adapter/src/main/java/eu/davidea/flexibleadapter/FlexibleAdapter.java @@ -2532,6 +2532,37 @@ public List getExpandedPositions() { return expandedPositions; } + /** + * Convenience method to determine the total number of items up to the subposition of expandable + * subitems + * + * @return item count, including recursive expansions, to the first level subposition item + */ + private int getRecursiveSubItemCount( @NonNull IExpandable parent) { + return getRecursiveSubItemCount(parent, parent.getSubItems().size()); + } + + /** + * Recursively determine the total number of items between a range of expandable subitems + * + * @return item count, including recursive expansions, to the first level subposition item + */ + private int getRecursiveSubItemCount( @NonNull IExpandable parent, int subPosition) { + int count = 0; + // Get the subItems + List subItems = parent.getSubItems(); + // Iterate through subItems + for(int index = 0; index < subPosition; index++) { + T tempSubItem = subItems.get(index); + // Check whether item is also expandable, and expanded + if(this.isExpandable(tempSubItem) && ((IExpandable) tempSubItem).isExpanded()) { + count += getRecursiveSubItemCount((IExpandable) tempSubItem); + } + count++; + } + return count; + } + /** * Expands an item that is {@code IExpandable} type, not yet expanded and if has subItems. *

If configured, automatic smooth scroll will be performed when necessary.

@@ -2647,7 +2678,7 @@ private int expand(int position, boolean expandAll, boolean init, boolean notify // Every time an expansion is requested, subItems must be taken from the // original Object and without the subItems marked hidden (removed) - List subItems = getExpandableList(expandable); + List subItems = getExpandableList(expandable, true); mItems.addAll(position + 1, subItems); subItemsCount = subItems.size(); // Save expanded state @@ -2763,8 +2794,8 @@ public int collapse(@IntRange(from = 0) int position, boolean notifyParent) { IExpandable expandable = (IExpandable) item; // Take the current subList (will improve the performance when collapseAll) - List subItems = getExpandableList(expandable); - int subItemsCount = subItems.size(), recursiveCount = 0; + List subItems = getExpandableList(expandable, true); + int subItemsCount = subItems.size(); Log.v("Request to Collapse on position=%s expanded=%s hasSubItemsSelected=%s", position, expandable.isExpanded(), hasSubItemsSelected(position, subItems)); @@ -2773,7 +2804,7 @@ public int collapse(@IntRange(from = 0) int position, boolean notifyParent) { (!hasSubItemsSelected(position, subItems) || getPendingRemovedItem(item) != null)) { // Recursive collapse of all sub expandable - recursiveCount = recursiveCollapse(position + 1, subItems, expandable.getExpansionLevel()); + recursiveCollapse(position + 1, subItems, expandable.getExpansionLevel()); mItems.removeAll(subItems); subItemsCount = subItems.size(); // Save expanded state @@ -2796,7 +2827,7 @@ public int collapse(@IntRange(from = 0) int position, boolean notifyParent) { Log.v("Collapsed %s subItems on position %s", subItemsCount, position); } - return subItemsCount + recursiveCount; + return subItemsCount; } private boolean collapseSHF(List scrollables, IExpandable expandable) { @@ -3162,7 +3193,7 @@ private boolean addSubItems(@IntRange(from = 0) int parentPosition, // Notify the adapter of the new addition to display it and animate it. // If parent is collapsed there's no need to add sub items. if (parent.isExpanded()) { - added = addItems(parentPosition + 1 + Math.max(0, subPosition), subItems); + added = addItems(parentPosition + 1 + getRecursiveSubItemCount(parent, subPosition), subItems); } // Notify the parent about the change if requested if (payload != null) notifyItemChanged(parentPosition, payload); @@ -4945,7 +4976,7 @@ private RestoreInfo getPendingRemovedItem(T item) { * @since 5.0.0-b1 */ private void createRestoreSubItemInfo(IExpandable expandable, T item) { - List siblings = getExpandableList(expandable); + List siblings = getExpandableList(expandable, true); int childPosition = siblings.indexOf(item); mRestoreList.add(new RestoreInfo((T) expandable, item, childPosition)); Log.v("Recycled SubItem %s with Parent position=%s", @@ -4972,19 +5003,40 @@ private void createRestoreItemInfo(int position, T item) { Log.v("Recycled Item %s on position=%s", mRestoreList.get(mRestoreList.size() - 1), position); } + /** * @param expandable the parent item - * @return the list of the subItems not hidden + * @return the list of the subItems not hidden, non-recursively * @since 5.0.0-b1 */ @NonNull private List getExpandableList(IExpandable expandable) { + return getExpandableList(expandable, false); + } + + /** + * @param expandable the parent item + * @return the list of the subItems not hidden + * @since 5.0.0-b1 + */ + @NonNull + private List getExpandableList(IExpandable expandable, boolean isRecursive) { List subItems = new ArrayList<>(); if (expandable != null && hasSubItems(expandable)) { List allSubItems = expandable.getSubItems(); for (T subItem : allSubItems) { // Pick up only no hidden items (doesn't get into account the filtered items) - if (!subItem.isHidden()) subItems.add(subItem); + if (!subItem.isHidden()) { + // Add the current subitem + subItems.add(subItem); + // If expandable, expanded, and of non-zero size, recursively add sub-subItems + if(this.isExpandable(subItem) && + isRecursive && + ((IExpandable) subItem).isExpanded() && + ((IExpandable) subItem).getSubItems().size() > 0) { + subItems.addAll(getExpandableList((IExpandable) subItem, true)); + } + } } } return subItems; @@ -4996,6 +5048,7 @@ private List getExpandableList(IExpandable expandable) { * @param startPosition helps to improve performance, so we can avoid a new search for position * @param subItems the list of sub items to check * @return true if at least 1 subItem is currently selected, false if no subItems are selected + * search is non-recursive * @since 5.0.0-b1 */ private boolean hasSubItemsSelected(int startPosition, List subItems) { @@ -5420,7 +5473,7 @@ public int getRestorePosition(boolean isChild) { // Assert the expandable children are collapsed recursiveCollapse(refPosition, getCurrentChildren((IExpandable) item), 0); } else if (isExpanded(item) && !isChild) { - refPosition += getExpandableList((IExpandable) item).size() + 1; + refPosition += getExpandableList((IExpandable) item, true).size() + 1; } else { refPosition++; } @@ -5548,14 +5601,12 @@ private void prepareItemsForUpdate(List newItems) { if (isExpanded(item)) { IExpandable expandable = (IExpandable) item; expandable.setExpanded(true); - List subItems = getExpandableList(expandable); + List subItems = getExpandableList(expandable, false); int itemCount = newItems.size(); if (position < itemCount) { newItems.addAll(position + 1, subItems); - position += subItems.size(); } else { newItems.addAll(subItems); - position = itemCount; } } // Display headers too