public ExpandableRecyclerViewWrapperAdapter(RecyclerViewExpandableItemManager manager, RecyclerView.Adapter<RecyclerView.ViewHolder> adapter, long[] expandedItemsSavedState) { super(adapter); mExpandableItemAdapter = getExpandableItemAdapter(adapter); if (mExpandableItemAdapter == null) { throw new IllegalArgumentException("adapter does not implement ExpandableItemAdapter"); } if (manager == null) { throw new IllegalArgumentException("manager cannot be null"); } mExpandableListManager = manager; mPositionTranslator = new ExpandablePositionTranslator(); mPositionTranslator.build( mExpandableItemAdapter, ExpandablePositionTranslator.BUILD_OPTION_DEFAULT, mExpandableListManager.getDefaultGroupsExpandedState()); if (expandedItemsSavedState != null) { // NOTE: do not call hook routines and listener methods mPositionTranslator.restoreExpandedGroupItems(expandedItemsSavedState, null, null, null); } }
public int getVisibleChildCount(int groupPosition) { if (isGroupExpanded(groupPosition)) { return getChildCount(groupPosition); } else { return 0; } }
/*package*/ int getCollapsedGroupsCount() { return mPositionTranslator.getCollapsedGroupsCount(); }
private void rebuildPositionTranslator() { if (mPositionTranslator != null) { long[] savedState = mPositionTranslator.getSavedStateArray(); mPositionTranslator.build( mExpandableItemAdapter, ExpandablePositionTranslator.BUILD_OPTION_DEFAULT, mExpandableListManager.getDefaultGroupsExpandedState()); // NOTE: do not call hook routines and listener methods mPositionTranslator.restoreExpandedGroupItems(savedState, null, null, null); } }
/*package*/ void expandAll() { if (!mPositionTranslator.isEmpty() && !mPositionTranslator.isAllExpanded()) { mPositionTranslator.build( mExpandableItemAdapter, ExpandablePositionTranslator.BUILD_OPTION_EXPANDED_ALL, mExpandableListManager.getDefaultGroupsExpandedState()); notifyDataSetChanged(); } }
final long expandableFromPosition = mPositionTranslator.getExpandablePosition(fromPosition); final int fromGroupPosition = ExpandableAdapterHelper.getPackedPositionGroup(expandableFromPosition); final int fromChildPosition = ExpandableAdapterHelper.getPackedPositionChild(expandableFromPosition); final long expandableToPosition = mPositionTranslator.getExpandablePosition(toPosition); final int toGroupPosition = ExpandableAdapterHelper.getPackedPositionGroup(expandableToPosition); final int toChildPosition = ExpandableAdapterHelper.getPackedPositionChild(expandableToPosition); mPositionTranslator.moveGroupItem(fromGroupPosition, toGroupPosition); actualToFlatPosition = toPosition; } else if (!fromIsGroup && !toIsGroup) { actualToFlatPosition = mPositionTranslator.getFlatPosition( ExpandableAdapterHelper.getPackedPositionForChild(fromGroupPosition, modToChildPosition)); mPositionTranslator.moveChildItem(fromGroupPosition, fromChildPosition, toGroupPosition, modToChildPosition); } else if (!fromIsGroup /*&& toIsGroup NOTE: toIsGroup is always true here*/) { if (toPosition < fromPosition) { modToChildPosition = mPositionTranslator.getChildCount(modToGroupPosition); if (mPositionTranslator.isGroupExpanded(toGroupPosition)) { modToChildPosition = mPositionTranslator.getChildCount(modToGroupPosition); final int lastIndex = Math.max(0, mPositionTranslator.getChildCount(modToGroupPosition) - 1); modToChildPosition = Math.min(modToChildPosition, lastIndex); if (mPositionTranslator.isGroupExpanded(toGroupPosition)) {
/*package*/ boolean collapseGroup(int groupPosition, boolean fromUser, Object payload) { if (!mPositionTranslator.isGroupExpanded(groupPosition)) { return false; } // call hook method if (!mExpandableItemAdapter.onHookGroupCollapse(groupPosition, fromUser, payload)) { return false; } if (mPositionTranslator.collapseGroup(groupPosition)) { final long packedPosition = ExpandableAdapterHelper.getPackedPositionForGroup(groupPosition); final int flatPosition = mPositionTranslator.getFlatPosition(packedPosition); final int childCount = mPositionTranslator.getChildCount(groupPosition); notifyItemRangeRemoved(flatPosition + 1, childCount); } { final long packedPosition = ExpandableAdapterHelper.getPackedPositionForGroup(groupPosition); final int flatPosition = mPositionTranslator.getFlatPosition(packedPosition); notifyItemChanged(flatPosition, payload); } // raise onGroupCollapse() event if (mOnGroupCollapseListener != null) { mOnGroupCollapseListener.onGroupCollapse(groupPosition, fromUser, payload); } return true; }
/*package*/ boolean expandGroup(int groupPosition, boolean fromUser, Object payload) { if (mPositionTranslator.isGroupExpanded(groupPosition)) { return false; } // call hook method if (!mExpandableItemAdapter.onHookGroupExpand(groupPosition, fromUser, payload)) { return false; } if (mPositionTranslator.expandGroup(groupPosition)) { final long packedPosition = ExpandableAdapterHelper.getPackedPositionForGroup(groupPosition); final int flatPosition = mPositionTranslator.getFlatPosition(packedPosition); final int childCount = mPositionTranslator.getChildCount(groupPosition); notifyItemRangeInserted(flatPosition + 1, childCount); } { final long packedPosition = ExpandableAdapterHelper.getPackedPositionForGroup(groupPosition); final int flatPosition = mPositionTranslator.getFlatPosition(packedPosition); notifyItemChanged(flatPosition, payload); } // raise onGroupExpand() event if (mOnGroupExpandListener != null) { mOnGroupExpandListener.onGroupExpand(groupPosition, fromUser, payload); } return true; }
final long draggingExpandablePosition = mPositionTranslator.getExpandablePosition(draggingFlatPosition); final int draggingGroupPosition = ExpandableAdapterHelper.getPackedPositionGroup(draggingExpandablePosition); final int draggingChildPosition = ExpandableAdapterHelper.getPackedPositionChild(draggingExpandablePosition); final long dropExpandablePosition = mPositionTranslator.getExpandablePosition(dropFlatPosition); final int dropGroupPosition = ExpandableAdapterHelper.getPackedPositionGroup(dropExpandablePosition); final int dropChildPosition = ExpandableAdapterHelper.getPackedPositionChild(dropExpandablePosition); canDrop = dropIsGroup; } else if (draggingFlatPosition < dropFlatPosition) { final boolean isDropGroupExpanded = mPositionTranslator.isGroupExpanded(dropGroupPosition); final int dropGroupVisibleChildren = mPositionTranslator.getVisibleChildCount(dropGroupPosition); if (dropIsGroup) { canDrop = (!isDropGroupExpanded); final boolean isDropGroupExpanded = mPositionTranslator.isGroupExpanded(dropGroupPosition); boolean canDrop; int modDropGroupPosition = dropGroupPosition; modDropChildPosition = 0; } else { modDropChildPosition = mPositionTranslator.getChildCount(modDropGroupPosition); if (modDropGroupPosition > 0) { modDropGroupPosition -= 1; modDropChildPosition = mPositionTranslator.getChildCount(modDropGroupPosition); canDrop = true; } else {
final long expandablePosition = mPositionTranslator.getExpandablePosition(flatPosition); final int groupPosition = ExpandableAdapterHelper.getPackedPositionGroup(expandablePosition); final int childPosition = ExpandableAdapterHelper.getPackedPositionChild(expandablePosition); final int lastGroup = Math.max(0, mExpandableItemAdapter.getGroupCount() - 1); final int start = 0; final int end = Math.max(start, mPositionTranslator.getItemCount() - mPositionTranslator.getVisibleChildCount(lastGroup) - 1); final long startPackedGroupPosition = ExpandableAdapterHelper.getPackedPositionForGroup(range.getStart()); final long endPackedGroupPosition = ExpandableAdapterHelper.getPackedPositionForGroup(range.getEnd()); final int start = mPositionTranslator.getFlatPosition(startPackedGroupPosition); int end = mPositionTranslator.getFlatPosition(endPackedGroupPosition); end += mPositionTranslator.getVisibleChildCount(range.getEnd()); return new ItemDraggableRange(start, Math.max(start, mPositionTranslator.getItemCount() - 1)); } else if (isGroupPositionRange(range)) { final long startPackedGroupPosition = ExpandableAdapterHelper.getPackedPositionForGroup(range.getStart()); final long endPackedGroupPosition = ExpandableAdapterHelper.getPackedPositionForGroup(range.getEnd()); final int end = mPositionTranslator.getFlatPosition(endPackedGroupPosition) + mPositionTranslator.getVisibleChildCount(range.getEnd()); int start = mPositionTranslator.getFlatPosition(startPackedGroupPosition) + 1; final int maxChildrenPos = Math.max(mPositionTranslator.getVisibleChildCount(groupPosition) - 1, 0); final int childStart = Math.min(range.getStart(), maxChildrenPos); final int childEnd = Math.min(range.getEnd(), maxChildrenPos); final long startPackedChildPosition = ExpandableAdapterHelper.getPackedPositionForChild(groupPosition, childStart); final long endPackedChildPosition = ExpandableAdapterHelper.getPackedPositionForChild(groupPosition, childEnd);
/*package*/ void collapseAll() { if (!mPositionTranslator.isEmpty() && !mPositionTranslator.isAllCollapsed()) { mPositionTranslator.build( mExpandableItemAdapter, ExpandablePositionTranslator.BUILD_OPTION_COLLAPSED_ALL, mExpandableListManager.getDefaultGroupsExpandedState()); notifyDataSetChanged(); } }
@Override protected void onHandleWrappedAdapterItemRangeRemoved(int positionStart, int itemCount) { if (itemCount == 1) { final long expandablePosition = mPositionTranslator.getExpandablePosition(positionStart); final int groupPosition = ExpandableAdapterHelper.getPackedPositionGroup(expandablePosition); final int childPosition = ExpandableAdapterHelper.getPackedPositionChild(expandablePosition); if (childPosition == RecyclerView.NO_POSITION) { mPositionTranslator.removeGroupItem(groupPosition); } else { mPositionTranslator.removeChildItem(groupPosition, childPosition); } } else { rebuildPositionTranslator(); } super.onHandleWrappedAdapterItemRangeRemoved(positionStart, itemCount); }
/*package*/ long getExpandablePosition(int flatPosition) { return mPositionTranslator.getExpandablePosition(flatPosition); }
@SuppressWarnings("unchecked") boolean onTapItem(@NonNull RecyclerView.ViewHolder holder, int position, int x, int y) { if (mExpandableItemAdapter == null) { return false; } //noinspection UnnecessaryLocalVariable final int flatPosition = position; final long expandablePosition = mPositionTranslator.getExpandablePosition(flatPosition); final int groupPosition = ExpandableAdapterHelper.getPackedPositionGroup(expandablePosition); final int childPosition = ExpandableAdapterHelper.getPackedPositionChild(expandablePosition); if (childPosition != RecyclerView.NO_POSITION) { return false; } final boolean expand = !(mPositionTranslator.isGroupExpanded(groupPosition)); boolean result = mExpandableItemAdapter.onCheckCanExpandOrCollapseGroup(holder, groupPosition, x, y, expand); if (!result) { return false; } if (expand) { expandGroup(groupPosition, true, null); } else { collapseGroup(groupPosition, true, null); } return true; }
if (expandGroup(position)) { if (expandListener != null) { expandListener.onGroupExpand(position, fromUser, null); if (collapseGroup(position)) { if (collapseListener != null) { collapseListener.onGroupCollapse(position, fromUser, null);
enlargeArraysIfNeeded(mGroupCount + n, true);
/*package*/ int getExpandedGroupsCount() { return mPositionTranslator.getExpandedGroupsCount(); }
final int startIndex = binarySearchGroupPositionByFlatPosition(mCachedGroupPosInfo, mEndOfCalculatedOffsetGroupPosition, flatPosition); long expandablePosition = ExpandableAdapterHelper.NO_EXPANDABLE_POSITION; int endOfCalculatedOffsetGroupPosition = mEndOfCalculatedOffsetGroupPosition;
@SuppressWarnings("unchecked") @Override public SwipeResultAction onSwipeItem(@NonNull RecyclerView.ViewHolder holder, int position, int result) { if (!(mExpandableItemAdapter instanceof BaseExpandableSwipeableItemAdapter)) { return null; } if (position == RecyclerView.NO_POSITION) { return null; } final BaseExpandableSwipeableItemAdapter<?, ?> adapter = (BaseExpandableSwipeableItemAdapter<?, ?>) mExpandableItemAdapter; //noinspection UnnecessaryLocalVariable final int flatPosition = position; final long expandablePosition = mPositionTranslator.getExpandablePosition(flatPosition); final int groupPosition = ExpandableAdapterHelper.getPackedPositionGroup(expandablePosition); final int childPosition = ExpandableAdapterHelper.getPackedPositionChild(expandablePosition); return ExpandableSwipeableItemInternalUtils.invokeOnSwipeItem( adapter, holder, groupPosition, childPosition, result); }
@SuppressWarnings("unchecked") @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) { if (mExpandableItemAdapter == null) { return; } final long expandablePosition = mPositionTranslator.getExpandablePosition(position); final int groupPosition = ExpandableAdapterHelper.getPackedPositionGroup(expandablePosition); final int childPosition = ExpandableAdapterHelper.getPackedPositionChild(expandablePosition); final int viewType = (holder.getItemViewType() & (~VIEW_TYPE_FLAG_IS_GROUP)); // update flags int flags = 0; if (childPosition == RecyclerView.NO_POSITION) { flags |= Constants.STATE_FLAG_IS_GROUP; } else { flags |= Constants.STATE_FLAG_IS_CHILD; } if (mPositionTranslator.isGroupExpanded(groupPosition)) { flags |= Constants.STATE_FLAG_IS_EXPANDED; } safeUpdateExpandStateFlags(holder, flags); correctItemDragStateFlags(holder, groupPosition, childPosition); if (childPosition == RecyclerView.NO_POSITION) { mExpandableItemAdapter.onBindGroupViewHolder(holder, groupPosition, viewType, payloads); } else { mExpandableItemAdapter.onBindChildViewHolder(holder, groupPosition, childPosition, viewType, payloads); } }