applyContentDimensions method
Called when the viewport's content extents are established.
The arguments are the minimum and maximum scroll extents respectively. The minimum will be equal to or less than the maximum. In the case of slivers, the minimum will be equal to or less than zero, the maximum will be equal to or greater than zero.
The maximum scroll extent has the viewport dimension subtracted from it. For instance, if there is 100.0 pixels of scrollable content, and the viewport is 80.0 pixels high, then the minimum scroll extent will typically be 0.0 and the maximum scroll extent will typically be 20.0, because there's only 20.0 pixels of actual scroll slack.
If applying the content dimensions changes the scroll offset, return false. Otherwise, return true. If you return false, the RenderViewport will be laid out again with the new scroll offset. This is expensive. (The return value is answering the question "did you accept these content dimensions unconditionally?"; if the new dimensions change the ViewportOffset's actual pixels value, then the viewport will need to be laid out again.)
This is called at least once each time the RenderViewport is laid out, even if the values have not changed. It may be called many times if the scroll offset is corrected (if this returns false). This is always called after applyViewportDimension, if that method is called.
Implementation
@override
bool applyContentDimensions(double minScrollExtent, double maxScrollExtent) {
assert(haveDimensions == (_lastMetrics != null));
if (!nearEqual(_minScrollExtent, minScrollExtent, Tolerance.defaultTolerance.distance) ||
!nearEqual(_maxScrollExtent, maxScrollExtent, Tolerance.defaultTolerance.distance) ||
_didChangeViewportDimensionOrReceiveCorrection ||
_lastAxis != axis) {
assert(minScrollExtent <= maxScrollExtent);
_minScrollExtent = minScrollExtent;
_maxScrollExtent = maxScrollExtent;
_lastAxis = axis;
final ScrollMetrics? currentMetrics = haveDimensions ? copyWith() : null;
_didChangeViewportDimensionOrReceiveCorrection = false;
_pendingDimensions = true;
if (haveDimensions && !correctForNewDimensions(_lastMetrics!, currentMetrics!)) {
return false;
}
_haveDimensions = true;
}
assert(haveDimensions);
if (_pendingDimensions) {
applyNewDimensions();
_pendingDimensions = false;
}
assert(!_didChangeViewportDimensionOrReceiveCorrection, 'Use correctForNewDimensions() (and return true) to change the scroll offset during applyContentDimensions().');
if (_isMetricsChanged()) {
// It is too late to send useful notifications, because the potential
// listeners have, by definition, already been built this frame. To make
// sure the notification is sent at all, we delay it until after the frame
// is complete.
if (!_haveScheduledUpdateNotification) {
scheduleMicrotask(didUpdateScrollMetrics);
_haveScheduledUpdateNotification = true;
}
_lastMetrics = copyWith();
}
return true;
}