Fix thumb size calculation (#36887)

Cupertino's thumb would jump up/down in size at the overscroll boundary, and this fixes it.
This commit is contained in:
Justin McCandless 2019-07-29 10:33:53 -07:00 committed by GitHub
parent 6f42a68ec4
commit c8be195e95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 1 deletions

View File

@ -214,6 +214,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
trackExtent * fractionVisible
);
final double fractionOverscrolled = 1.0 - extentInside / _lastMetrics.viewportDimension;
final double safeMinLength = math.min(minLength, trackExtent);
final double newMinLength = (beforeExtent > 0 && afterExtent > 0)
// Thumb extent is no smaller than minLength if scrolling normally.
@ -229,7 +230,7 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
// [0.8, 1.0] to [0.0, 1.0], so 0% to 20% of overscroll will produce
// values for the thumb that range between minLength and the smallest
// possible value, minOverscrollLength.
: safeMinLength * ((fractionVisible - 0.8).clamp(0.0, 0.2) / 0.2);
: safeMinLength * (1.0 - fractionOverscrolled.clamp(0.0, 0.2) / 0.2);
// The `thumbExtent` should be no greater than `trackSize`, otherwise
// the scrollbar may scroll towards the wrong direction.

View File

@ -371,6 +371,77 @@ void main() {
});
});
testWidgets('thumb resizes gradually on overscroll', (WidgetTester tester) async {
const EdgeInsets padding = EdgeInsets.fromLTRB(1, 2, 3, 4);
const Size size = Size(60, 300);
final double scrollExtent = size.height * 10;
final ScrollMetrics metrics = defaultMetrics.copyWith(
minScrollExtent: 0,
maxScrollExtent: scrollExtent,
axisDirection: AxisDirection.down,
viewportDimension: size.height,
);
const double minOverscrollLength = 8.0;
final ScrollbarPainter p = _buildPainter(
padding: padding,
scrollMetrics: metrics,
minLength: 36.0,
minOverscrollLength: 8.0,
);
// No overscroll gives a full sized thumb.
p.update(
metrics.copyWith(
pixels: 0.0,
),
AxisDirection.down,
);
p.paint(testCanvas, size);
final double fullThumbExtent = captureRect().height;
expect(fullThumbExtent, greaterThan(_kMinThumbExtent));
// Scrolling to the middle also gives a full sized thumb.
p.update(
metrics.copyWith(
pixels: scrollExtent / 2,
),
AxisDirection.down,
);
p.paint(testCanvas, size);
expect(captureRect().height, closeTo(fullThumbExtent, .000001));
// Scrolling just to the very end also gives a full sized thumb.
p.update(
metrics.copyWith(
pixels: scrollExtent,
),
AxisDirection.down,
);
p.paint(testCanvas, size);
expect(captureRect().height, closeTo(fullThumbExtent, .000001));
// Scrolling just past the end shrinks the thumb slightly.
p.update(
metrics.copyWith(
pixels: scrollExtent * 1.001,
),
AxisDirection.down,
);
p.paint(testCanvas, size);
expect(captureRect().height, closeTo(fullThumbExtent, 2.0));
// Scrolling way past the end shrinks the thumb to minimum.
p.update(
metrics.copyWith(
pixels: double.infinity,
),
AxisDirection.down,
);
p.paint(testCanvas, size);
expect(captureRect().height, minOverscrollLength);
});
test('should scroll towards the right direction',
() {
const Size size = Size(60, 80);