sortDescendants method
Sorts the given descendants
into focus order.
Subclasses should override this to implement a different sort for next and previous to use in their ordering. If the returned iterable omits a node that is a descendant of the given scope, then the user will be unable to use next/previous keyboard traversal to reach that node.
The node used to initiate the traversal (the one passed to next or
previous) is passed as currentNode
.
Having the current node in the list is what allows the algorithm to
determine which nodes are adjacent to the current node. If the
currentNode
is removed from the list, then the focus will be unchanged
when next or previous are called, and they will return false.
This is not used for directional focus (inDirection), only for determining the focus order for next and previous.
When implementing an override for this function, be sure to use mergeSort instead of Dart's default list sorting algorithm when sorting items, since the default algorithm is not stable (items deemed to be equal can appear in arbitrary order, and change positions between sorts), whereas mergeSort is stable.
Implementation
@override
Iterable<FocusNode> sortDescendants(Iterable<FocusNode> descendants, FocusNode currentNode) {
final FocusTraversalPolicy secondaryPolicy = secondary ?? ReadingOrderTraversalPolicy();
final Iterable<FocusNode> sortedDescendants = secondaryPolicy.sortDescendants(descendants, currentNode);
final List<FocusNode> unordered = <FocusNode>[];
final List<_OrderedFocusInfo> ordered = <_OrderedFocusInfo>[];
for (final FocusNode node in sortedDescendants) {
final FocusOrder? order = FocusTraversalOrder.maybeOf(node.context!);
if (order != null) {
ordered.add(_OrderedFocusInfo(node: node, order: order));
} else {
unordered.add(node);
}
}
mergeSort<_OrderedFocusInfo>(ordered, compare: (_OrderedFocusInfo a, _OrderedFocusInfo b) {
assert(
a.order.runtimeType == b.order.runtimeType,
'When sorting nodes for determining focus order, the order (${a.order}) of '
"node ${a.node}, isn't the same type as the order (${b.order}) of ${b.node}. "
"Incompatible order types can't be compared. Use a FocusTraversalGroup to group "
'similar orders together.',
);
return a.order.compareTo(b.order);
});
return ordered.map<FocusNode>((_OrderedFocusInfo info) => info.node).followedBy(unordered);
}