reorderChildren method
void
reorderChildren(})
Reorders the children of parentKey to match orderedKeys.
orderedKeys must contain exactly the current live (non-pending-deletion)
children of parentKey, with no duplicates; violating that throws an
ArgumentError, as does an unknown parentKey. Expansion state,
animation state, and measured extents are preserved.
When animate is true and the children are visible, shifted rows
get a paint-only FLIP slide over slideDuration/slideCurve; both
default to the controller's animationStyle reorderSlide spec
when omitted.
Implementation
void reorderChildren(
TKey parentKey,
List<TKey> orderedKeys, {
bool animate = true,
Duration? slideDuration,
Curve? slideCurve,
}) {
if (!_hasKey(parentKey)) {
throw ArgumentError.value(parentKey, "parentKey", "not found");
}
final currentChildren = _childListOf(parentKey) ?? <TKey>[];
final pendingChildren = <TKey>[];
final liveChildSet = <TKey>{};
for (final k in currentChildren) {
if (_isPendingDeletion(k)) {
pendingChildren.add(k);
} else {
liveChildSet.add(k);
}
}
// Validate in all build modes: see reorderRoots for rationale.
if (orderedKeys.length != liveChildSet.length ||
orderedKeys.toSet().length != orderedKeys.length ||
!liveChildSet.containsAll(orderedKeys)) {
throw ArgumentError.value(
orderedKeys,
"orderedKeys",
"must contain exactly the current live children of $parentKey with "
"no duplicates",
);
}
// Stage the FLIP slide baseline BEFORE mutating, but only when the children
// are strictly visible (parent + ancestors expanded). The
// _markVisibleOrderDirty below fires for the same `visible` case, so the
// next
// layout consumes the baseline and slides shifted rows. Gating on `visible`
// avoids a pointless slide for a collapsed reorder and never strands an
// unconsumed baseline.
final visible =
_isExpandedKey(parentKey) && _ancestorsExpandedFast(parentKey);
// Family kill switch: see reorderRoots.
if (animate &&
visible &&
_animationStyle.reorderSlide.duration != Duration.zero) {
// Null timing resolves to the style's reorderSlide spec.
_stageSlideBaselineOnHosts(
duration: slideDuration ?? _animationStyle.reorderSlide.duration,
curve: slideCurve ?? _animationStyle.reorderSlide.curve,
);
}
_setChildList(parentKey, [...orderedKeys, ...pendingChildren]);
// Raw sibling-list write above; invalidate cached live indices.
_liveIndexCache.bump();
bool needsVisibleRebuild = visible;
if (!needsVisibleRebuild) {
// Even if the parent is not expanded, children may still be present
// in the visible order because they are mid-animation (collapse in
// progress, pending-deletion exit). Those entries would otherwise
// retain the old order until the animation completes.
for (final child in _childListOf(parentKey)!) {
if (_hasOperationGroup(child) ||
_activeBulkGroup?.members.contains(child) == true ||
_hasStandalone(child)) {
needsVisibleRebuild = true;
break;
}
}
}
if (needsVisibleRebuild) {
_markVisibleOrderDirty();
}
// See reorderRoots: the reordered rows' own positions are builder
// inputs, so they refresh.
_notifyStructural(affectedKeys: _siblingRefreshOrToken(parentKey));
}