From 52bf9dbbd72ecc787474da223c32d2368a4ad49e Mon Sep 17 00:00:00 2001 From: xubaolin Date: Tue, 3 Aug 2021 12:40:04 +0800 Subject: [PATCH] update ScrollMetricsNotification (#87421) --- .../lib/src/widgets/scroll_position.dart | 2 +- .../flutter/lib/src/widgets/scrollbar.dart | 24 +++++++------------ .../test/cupertino/scrollbar_test.dart | 12 ++++++++-- .../widgets/scroll_notification_test.dart | 3 ++- .../flutter/test/widgets/scrollbar_test.dart | 14 +++++++++-- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/packages/flutter/lib/src/widgets/scroll_position.dart b/packages/flutter/lib/src/widgets/scroll_position.dart index a2272633ff..60e78b3a0a 100644 --- a/packages/flutter/lib/src/widgets/scroll_position.dart +++ b/packages/flutter/lib/src/widgets/scroll_position.dart @@ -558,7 +558,7 @@ abstract class ScrollPosition extends ViewportOffset with ScrollMetrics { // It isn't safe to trigger the ScrollMetricsNotification if we are in // the middle of rendering the frame, the developer is likely to schedule // a new frame(build scheduled during frame is illegal). - if (_lastMetrics != null && !_haveScheduledUpdateNotification) { + if (!_haveScheduledUpdateNotification) { scheduleMicrotask(didUpdateScrollMetrics); _haveScheduledUpdateNotification = true; } diff --git a/packages/flutter/lib/src/widgets/scrollbar.dart b/packages/flutter/lib/src/widgets/scrollbar.dart index b23d6876db..c91089f390 100644 --- a/packages/flutter/lib/src/widgets/scrollbar.dart +++ b/packages/flutter/lib/src/widgets/scrollbar.dart @@ -1224,25 +1224,16 @@ class RawScrollbarState extends State with TickerProv @override void didChangeDependencies() { super.didChangeDependencies(); - _maybeTriggerScrollbar(); + assert(_debugScheduleCheckHasValidScrollPosition()); } - // Waits one frame and cause an empty scroll event (zero delta pixels). - // - // This allows the thumb to show immediately when isAlwaysShown is true. - // A scroll event is required in order to paint the thumb. - void _maybeTriggerScrollbar() { + bool _debugScheduleCheckHasValidScrollPosition() { + if (!showScrollbar) + return true; WidgetsBinding.instance!.addPostFrameCallback((Duration duration) { - final ScrollController? scrollController = widget.controller ?? PrimaryScrollController.of(context); - if (showScrollbar) { - _fadeoutTimer?.cancel(); - // Wait one frame and cause an empty scroll event. This allows the - // thumb to show immediately when isAlwaysShown is true. A scroll - // event is required in order to paint the thumb. - assert(_debugCheckHasValidScrollPosition()); - scrollController!.position.didUpdateScrollPositionBy(0); - } + assert(_debugCheckHasValidScrollPosition()); }); + return true; } void _validateInteractions(AnimationStatus status) { @@ -1365,7 +1356,8 @@ class RawScrollbarState extends State with TickerProv super.didUpdateWidget(oldWidget); if (widget.isAlwaysShown != oldWidget.isAlwaysShown) { if (widget.isAlwaysShown == true) { - _maybeTriggerScrollbar(); + assert(_debugScheduleCheckHasValidScrollPosition()); + _fadeoutTimer?.cancel(); _fadeoutAnimationController.animateTo(1.0); } else { _fadeoutAnimationController.reverse(); diff --git a/packages/flutter/test/cupertino/scrollbar_test.dart b/packages/flutter/test/cupertino/scrollbar_test.dart index bbdfa21b7d..0359f11f5d 100644 --- a/packages/flutter/test/cupertino/scrollbar_test.dart +++ b/packages/flutter/test/cupertino/scrollbar_test.dart @@ -5,6 +5,7 @@ import 'dart:ui' as ui; import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -389,9 +390,16 @@ void main() { ); } + final FlutterExceptionHandler? handler = FlutterError.onError; + FlutterErrorDetails? error; + FlutterError.onError = (FlutterErrorDetails details) { + error = details; + }; + await tester.pumpWidget(viewWithScroll()); - final AssertionError exception = tester.takeException() as AssertionError; - expect(exception, isAssertionError); + expect(error, isNotNull); + + FlutterError.onError = handler; }, ); diff --git a/packages/flutter/test/widgets/scroll_notification_test.dart b/packages/flutter/test/widgets/scroll_notification_test.dart index 1f9d512609..e56b4cd637 100644 --- a/packages/flutter/test/widgets/scroll_notification_test.dart +++ b/packages/flutter/test/widgets/scroll_notification_test.dart @@ -21,8 +21,9 @@ void main() { ); } await tester.pumpWidget(buildFrame(1200.0)); - expect(events.length, 0); + expect(events.length, 1); + events.clear(); await tester.pumpWidget(buildFrame(1000.0)); // Change the content dimensions will trigger a new event. expect(events.length, 1); diff --git a/packages/flutter/test/widgets/scrollbar_test.dart b/packages/flutter/test/widgets/scrollbar_test.dart index 400805793f..c05584253f 100644 --- a/packages/flutter/test/widgets/scrollbar_test.dart +++ b/packages/flutter/test/widgets/scrollbar_test.dart @@ -4,6 +4,7 @@ import 'dart:ui' as ui; +import 'package:flutter/foundation.dart'; import 'package:flutter/src/physics/utils.dart' show nearEqual; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -1143,6 +1144,12 @@ void main() { }); testWidgets('RawScrollbar.isAlwaysShown asserts that a ScrollPosition is attached', (WidgetTester tester) async { + final FlutterExceptionHandler? handler = FlutterError.onError; + FlutterErrorDetails? error; + FlutterError.onError = (FlutterErrorDetails details) { + error = details; + }; + await tester.pumpWidget( Directionality( textDirection: TextDirection.ltr, @@ -1163,12 +1170,15 @@ void main() { ), ); await tester.pumpAndSettle(); - final AssertionError exception = tester.takeException() as AssertionError; - expect(exception, isAssertionError); + + expect(error, isNotNull); + final AssertionError exception = error!.exception as AssertionError; expect( exception.message, contains("The Scrollbar's ScrollController has no ScrollPosition attached."), ); + + FlutterError.onError = handler; }); testWidgets('Interactive scrollbars should have a valid scroll controller', (WidgetTester tester) async {