scrollUntilVisible method
Repeatedly scroll the widget located by scrollable
by dxScroll
and
dyScroll
until item
is visible, and then use scrollIntoView to
ensure the item's final position matches alignment
.
The scrollable
must locate the scrolling widget that contains item
.
Typically find.byType('ListView')
or find.byType('CustomScrollView')
.
At least one of dxScroll
and dyScroll
must be non-zero.
If item
is below the currently visible items, then specify a negative
value for dyScroll
that's a small enough increment to expose item
without potentially scrolling it up and completely out of view. Similarly
if item
is above, then specify a positive value for dyScroll
.
If item
is to the right of the currently visible items, then
specify a negative value for dxScroll
that's a small enough increment to
expose item
without potentially scrolling it up and completely out of
view. Similarly if item
is to the left, then specify a positive value
for dyScroll
.
The timeout
value should be long enough to accommodate as many scrolls
as needed to bring an item into view. The default is 10 seconds.
Implementation
Future<void> scrollUntilVisible(SerializableFinder scrollable, SerializableFinder item, {
double alignment = 0.0,
double dxScroll = 0.0,
double dyScroll = 0.0,
Duration timeout = const Duration(seconds: 10),
}) async {
assert(scrollable != null);
assert(item != null);
assert(alignment != null);
assert(dxScroll != null);
assert(dyScroll != null);
assert(dxScroll != 0.0 || dyScroll != 0.0);
assert(timeout != null);
// Kick off an (unawaited) waitFor that will complete when the item we're
// looking for finally scrolls onscreen. We add an initial pause to give it
// the chance to complete if the item is already onscreen; if not, scroll
// repeatedly until we either find the item or time out.
bool isVisible = false;
waitFor(item, timeout: timeout).then<void>((_) { isVisible = true; });
await Future<void>.delayed(const Duration(milliseconds: 500));
while (!isVisible) {
await scroll(scrollable, dxScroll, dyScroll, const Duration(milliseconds: 100));
await Future<void>.delayed(const Duration(milliseconds: 500));
}
return scrollIntoView(item, alignment: alignment);
}