setPixels method
Update the scroll position (pixels) to a given pixel value.
This should only be called by the current ScrollActivity, either during the transient callback phase or in response to user input.
Returns the overscroll, if any. If the return value is 0.0, that means
that pixels now returns the given value. If the return value is
positive, then pixels is less than the requested value by the given
amount (overscroll past the max extent), and if it is negative, it is
greater than the requested value by the given amount (underscroll past
the min extent).
The amount of overscroll is computed by applyBoundaryConditions.
The amount of the change that is applied is reported using didUpdateScrollPositionBy. If there is any overscroll, it is reported using didOverscrollBy.
Implementation
@override
double setPixels(double newPixels) {
if (pixels == newPixels) return 0.0;
// Request the final consumption to ensure [lentPixels] recovers to zero.
if (lentPixels + newPixels == minScrollExtent) {
_ensureLentPixels();
return setPostPixels(minScrollExtent, 0, 0);
}
final bool isOldOverscrolledForward = totalPixels < super.minScrollExtent;
final bool isOldOverscrolledBackward = totalPixels > super.maxScrollExtent;
final bool isNewOverscrolledForward =
lentPixels + newPixels < super.minScrollExtent;
final bool isNewOverscrolledBackward =
lentPixels + newPixels > super.maxScrollExtent;
final bool isOldOverscrolled =
isOldOverscrolledForward || isOldOverscrolledBackward;
final bool isNewOverscrolled =
isNewOverscrolledForward || isNewOverscrolledBackward;
// When the overscroll direction immediately switches to
// the forward or backward direction, or vice versa.
if (isOldOverscrolledForward && isNewOverscrolledBackward ||
isOldOverscrolledBackward && isNewOverscrolledForward) {
_ensureLentPixels();
}
// Handling the case where previously in an overscrolled state,
// but now the overscroll has resolved.
if (isOldOverscrolled && !isNewOverscrolled) {
if (totalPixels < minScrollExtent) {
correctPixels(super.minScrollExtent);
} else {
correctPixels(super.maxScrollExtent);
}
// Ensures that the remaining [lentPixels] are fully consumed
// since it is no longer an bouncing overscroll.
if (lentPixels.abs() > precisionErrorTolerance) {
_ensureLentPixels();
}
} else if (isOldOverscrolledForward && isNewOverscrolledBackward) {
// Transition from forward overscroll to backward overscroll.
correctPixels(super.maxScrollExtent);
} else if (isOldOverscrolledBackward && isNewOverscrolledForward) {
// Transition from backward overscroll to forward overscroll.
correctPixels(super.minScrollExtent);
}
final double clipedOverscroll = applyBoundaryConditions(newPixels);
final double systemOverscroll = overscrollOf(
newPixels,
minScrollExtent,
maxScrollExtent,
);
final double overDelta = systemOverscroll - clipedOverscroll;
if (pixels + overDelta < minScrollExtent ||
pixels + overDelta > maxScrollExtent) {
isNestedScrolling = true;
}
final double available = pixels - newPixels;
final double consumed = _preScroll(available);
// When all new scroll offset are consumed.
if ((consumed - available).abs() < precisionErrorTolerance) {
isNestedScrolling = true;
return 0.0;
}
return setPostPixels(
newPixels + consumed, clipedOverscroll, systemOverscroll);
}