scrollTo method
Scrolls until target is on screen, swiping the largest scrollable on
screen, or the one within finds.
Implementation
Future<void> scrollTo(Object target, {Object? within}) async {
final PlaybookFinder finder = Find.target(target);
final PlaybookFinder? container = within == null
? null
: Find.target(within);
bool backwards = false;
int reveals = 0;
for (int swipes = 0; swipes < 200; swipes++) {
_checkStopped();
final PlaybookTree tree = _tree();
final List<Element> matches = finder.find(tree);
for (final Element element in matches) {
if (_centerVisible(element)) return;
}
if (matches.isNotEmpty && reveals < 4) {
reveals++;
await _reveal(matches.first);
continue;
}
final ScrollableState? scrollable = _scrollableIn(tree, container);
if (scrollable == null) {
throw PlaybookFailure(
container == null
? 'There\'s nothing to scroll on screen to find '
'${finder.description}.'
: 'Could not find ${container.description} to scroll.',
visibleText: tree.visibleText(),
);
}
final ScrollPosition position = scrollable.position;
final bool atEdge = backwards
? position.pixels <= position.minScrollExtent + 0.5
: position.pixels >= position.maxScrollExtent - 0.5;
if (atEdge) {
if (backwards) {
throw PlaybookFailure(
'Scrolled through the whole list and could not find '
'${finder.description}.',
visibleText: tree.visibleText(),
);
}
backwards = true;
continue;
}
final double extent = position.viewportDimension;
await _scrollBy(scrollable, (backwards ? -0.6 : 0.6) * extent);
}
throw PlaybookFailure(
'Gave up scrolling to ${finder.description} after 200 swipes.',
);
}