Revert "improve the scrollbar behavior when viewport size changed (#76102)" (#80059)

This commit is contained in:
Kate Lovett 2021-04-08 18:09:03 -05:00 committed by GitHub
parent 913c57021d
commit 58c4bd1063
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 88 additions and 133 deletions

View file

@ -276,21 +276,14 @@ class ScrollbarPainter extends ChangeNotifier implements CustomPainter {
Rect? _trackRect; Rect? _trackRect;
late double _thumbOffset; late double _thumbOffset;
/// Update with new [ScrollMetrics]. If the metrics change, the scrollbar will /// Update with new [ScrollMetrics]. The scrollbar will show and redraw itself
/// show and redraw itself based on these new metrics. /// based on these new metrics.
/// ///
/// The scrollbar will remain on screen. /// The scrollbar will remain on screen.
void update( void update(
ScrollMetrics metrics, ScrollMetrics metrics,
AxisDirection axisDirection, AxisDirection axisDirection,
) { ) {
if (_lastMetrics != null &&
_lastMetrics!.extentBefore == metrics.extentBefore &&
_lastMetrics!.extentInside == metrics.extentInside &&
_lastMetrics!.extentAfter == metrics.extentAfter &&
_lastAxisDirection == axisDirection)
return;
_lastMetrics = metrics; _lastMetrics = metrics;
_lastAxisDirection = axisDirection; _lastAxisDirection = axisDirection;
notifyListeners(); notifyListeners();
@ -937,17 +930,16 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
@override @override
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
_maybeRequestEmptyScrollEvent(); _maybeTriggerScrollbar();
} }
// Waits one frame and cause an empty scroll event (zero delta pixels). // Waits one frame and cause an empty scroll event (zero delta pixels).
// //
// This allows the thumb to show immediately when isAlwaysShown is true. // This allows the thumb to show immediately when isAlwaysShown is true.
// A scroll event is required in order to paint the thumb. // A scroll event is required in order to paint the thumb.
void _maybeRequestEmptyScrollEvent() { void _maybeTriggerScrollbar() {
if (!showScrollbar)
return;
WidgetsBinding.instance!.addPostFrameCallback((Duration duration) { WidgetsBinding.instance!.addPostFrameCallback((Duration duration) {
if (showScrollbar) {
_fadeoutTimer?.cancel(); _fadeoutTimer?.cancel();
// Wait one frame and cause an empty scroll event. This allows the // Wait one frame and cause an empty scroll event. This allows the
// thumb to show immediately when isAlwaysShown is true. A scroll // thumb to show immediately when isAlwaysShown is true. A scroll
@ -1021,6 +1013,7 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
return true; return true;
}()); }());
scrollController!.position.didUpdateScrollPositionBy(0); scrollController!.position.didUpdateScrollPositionBy(0);
}
}); });
} }
@ -1042,16 +1035,15 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
@override @override
void didUpdateWidget(T oldWidget) { void didUpdateWidget(T oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
// If `isAlwaysShown` is true and does not change, if (widget.isAlwaysShown != oldWidget.isAlwaysShown) {
// it may be necessary to trigger a scroll event to show or hide the bar when the
// scrollable widget viewport size changed.
if (widget.isAlwaysShown == true) { if (widget.isAlwaysShown == true) {
_maybeRequestEmptyScrollEvent(); _maybeTriggerScrollbar();
_fadeoutAnimationController.animateTo(1.0); _fadeoutAnimationController.animateTo(1.0);
} else if (widget.isAlwaysShown != oldWidget.isAlwaysShown) { } else {
_fadeoutAnimationController.reverse(); _fadeoutAnimationController.reverse();
} }
} }
}
void _updateScrollPosition(double primaryDelta) { void _updateScrollPosition(double primaryDelta) {
assert(_currentController != null); assert(_currentController != null);
@ -1211,19 +1203,13 @@ class RawScrollbarState<T extends RawScrollbar> extends State<T> with TickerProv
return false; return false;
final ScrollMetrics metrics = notification.metrics; final ScrollMetrics metrics = notification.metrics;
if (metrics.maxScrollExtent <= metrics.minScrollExtent) { if (metrics.maxScrollExtent <= metrics.minScrollExtent)
// Hide the bar when the Scrollable widget has no space to scroll.
if (_fadeoutAnimationController.status != AnimationStatus.dismissed
&& _fadeoutAnimationController.status != AnimationStatus.reverse)
_fadeoutAnimationController.reverse();
return false; return false;
}
if (notification is ScrollUpdateNotification || if (notification is ScrollUpdateNotification ||
notification is OverscrollNotification) { notification is OverscrollNotification) {
// Any movements always makes the scrollbar start showing up. // Any movements always makes the scrollbar start showing up.
if (_fadeoutAnimationController.status != AnimationStatus.forward if (_fadeoutAnimationController.status != AnimationStatus.forward)
&& _fadeoutAnimationController.status != AnimationStatus.completed)
_fadeoutAnimationController.forward(); _fadeoutAnimationController.forward();
_fadeoutTimer?.cancel(); _fadeoutTimer?.cancel();

View file

@ -1152,35 +1152,4 @@ void main() {
), ),
); );
}); });
testWidgets('The bar can show or hide when the viewport size change', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
Widget buildFrame(double height) {
return Directionality(
textDirection: TextDirection.ltr,
child: MediaQuery(
data: const MediaQueryData(),
child: RawScrollbar(
controller: scrollController,
isAlwaysShown: true,
child: SingleChildScrollView(
controller: scrollController,
child: SizedBox(width: double.infinity, height: height)
),
),
),
);
}
await tester.pumpWidget(buildFrame(600.0));
await tester.pumpAndSettle();
expect(find.byType(RawScrollbar), isNot(paints..rect())); // Not shown.
await tester.pumpWidget(buildFrame(600.1));
await tester.pumpAndSettle();
expect(find.byType(RawScrollbar), paints..rect()..rect()); // Show the bar.
await tester.pumpWidget(buildFrame(600.0));
await tester.pumpAndSettle();
expect(find.byType(RawScrollbar), isNot(paints..rect())); // Hide the bar.
});
} }