diff --git a/packages/flutter/lib/src/material/refresh_indicator.dart b/packages/flutter/lib/src/material/refresh_indicator.dart index 0bb5ec7f31..906fd024be 100644 --- a/packages/flutter/lib/src/material/refresh_indicator.dart +++ b/packages/flutter/lib/src/material/refresh_indicator.dart @@ -383,12 +383,12 @@ class RefreshIndicatorState extends State with TickerProviderS return false; } - bool _handleGlowNotification(OverscrollIndicatorNotification notification) { + bool _handleIndicatorNotification(OverscrollIndicatorNotification notification) { if (notification.depth != 0 || !notification.leading) { return false; } if (_mode == _RefreshIndicatorMode.drag) { - notification.disallowGlow(); + notification.disallowIndicator(); return true; } return false; @@ -535,7 +535,7 @@ class RefreshIndicatorState extends State with TickerProviderS final Widget child = NotificationListener( onNotification: _handleScrollNotification, child: NotificationListener( - onNotification: _handleGlowNotification, + onNotification: _handleIndicatorNotification, child: widget.child, ), ); diff --git a/packages/flutter/lib/src/widgets/overscroll_indicator.dart b/packages/flutter/lib/src/widgets/overscroll_indicator.dart index 1c1297c513..124b0910c6 100644 --- a/packages/flutter/lib/src/widgets/overscroll_indicator.dart +++ b/packages/flutter/lib/src/widgets/overscroll_indicator.dart @@ -234,7 +234,7 @@ class _GlowingOverscrollIndicatorState extends State if (_lastNotificationType is! OverscrollNotification) { final OverscrollIndicatorNotification confirmationNotification = OverscrollIndicatorNotification(leading: isLeading); confirmationNotification.dispatch(context); - _accepted[isLeading] = confirmationNotification._accepted; + _accepted[isLeading] = confirmationNotification.accepted; if (_accepted[isLeading]!) { controller!._paintOffset = confirmationNotification.paintOffset; } @@ -714,7 +714,7 @@ class _StretchingOverscrollIndicatorState extends State( + onNotification: (ScrollNotification notification) { + if (notification is OverscrollNotification + && lastNotification is! OverscrollNotification) { + final OverscrollIndicatorNotification confirmationNotification = OverscrollIndicatorNotification(leading: true); + confirmationNotification.dispatch(context); + glowAccepted = confirmationNotification.accepted; + } + lastNotification = notification; + return false; + }, + child: ListView( + physics: const AlwaysScrollableScrollPhysics(), + children: ['A', 'B', 'C', 'D', 'E', 'F'].map((String item) { + return SizedBox( + height: 200.0, + child: Text(item), + ); + }).toList(), + ), + ); + } + ), + ), + ), + ); + + expect(find.byType(StretchingOverscrollIndicator), findsNothing); + expect(find.byType(GlowingOverscrollIndicator), findsOneWidget); + + await tester.fling(find.text('A'), const Offset(0.0, 300.0), 1000.0); + await tester.pump(); + + await tester.pump(const Duration(seconds: 1)); // finish the scroll animation + await tester.pump(const Duration(seconds: 1)); // finish the indicator settle animation + await tester.pump(const Duration(seconds: 1)); // finish the indicator hide animation + expect(refreshCalled, true); + expect(glowAccepted, false); + }); + + testWidgets('RefreshIndicator disallows indicator - stretch', (WidgetTester tester) async { + refreshCalled = false; + bool stretchAccepted = true; + ScrollNotification? lastNotification; + + await tester.pumpWidget( + MaterialApp( + theme: ThemeData.light().copyWith(useMaterial3: true), + home: RefreshIndicator( + onRefresh: refresh, + child: Builder( + builder: (BuildContext context) { + return NotificationListener( + onNotification: (ScrollNotification notification) { + if (notification is OverscrollNotification + && lastNotification is! OverscrollNotification) { + final OverscrollIndicatorNotification confirmationNotification = OverscrollIndicatorNotification(leading: true); + confirmationNotification.dispatch(context); + stretchAccepted = confirmationNotification.accepted; + } + lastNotification = notification; + return false; + }, + child: ListView( + physics: const AlwaysScrollableScrollPhysics(), + children: ['A', 'B', 'C', 'D', 'E', 'F'].map((String item) { + return SizedBox( + height: 200.0, + child: Text(item), + ); + }).toList(), + ), + ); + } + ), + ), + ), + ); + + expect(find.byType(StretchingOverscrollIndicator), findsOneWidget); + expect(find.byType(GlowingOverscrollIndicator), findsNothing); + + await tester.fling(find.text('A'), const Offset(0.0, 300.0), 1000.0); + await tester.pump(); + + await tester.pump(const Duration(seconds: 1)); // finish the scroll animation + await tester.pump(const Duration(seconds: 1)); // finish the indicator settle animation + await tester.pump(const Duration(seconds: 1)); // finish the indicator hide animation + expect(refreshCalled, true); + expect(stretchAccepted, false); + }); }