_ScrollablePositionedListState._scrollTo has a mistake.
darkstarx opened this issue · comments
Serj Elokhin commented
if _isTransitioning
, it returns immediately and the client code triggers immediately as well 'cause there's no any Future to wait for to know when the scrolling completes. That is a bug.
You must use Completer
to notify the client code about finishing the asynchronous scrolling initiated in the post-frame callback.
Future<void> _scrollTo({
required int index,
required double alignment,
required Duration duration,
Curve curve = Curves.linear,
required List<double> opacityAnimationWeights,
}) async {
if (index > widget.itemCount - 1) {
index = widget.itemCount - 1;
}
if (_isTransitioning) {
_stopScroll(canceled: true);
// HERE we must wait until the internal call to _startScroll completes!!!
SchedulerBinding.instance.addPostFrameCallback((_) {
_startScroll(
index: index,
alignment: alignment,
duration: duration,
curve: curve,
opacityAnimationWeights: opacityAnimationWeights,
);
});
} else {
await _startScroll(
index: index,
alignment: alignment,
duration: duration,
curve: curve,
opacityAnimationWeights: opacityAnimationWeights,
);
}
}
Tom Robinson commented
So I think the problem shows up when the client calling here waits on the returned future as an indicator that the scrolling is done, but currently the future resolves potentially before the scrolling finishes. Let me see if I can fix that without adding other problems.