scrollTo method

Future<void> scrollTo(
  1. Object target, {
  2. Object? within,
})

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.',
  );
}