From f1d04a46cb31903383a26e82572bfdd57330c9fb Mon Sep 17 00:00:00 2001 From: Chinmoy Date: Fri, 18 Aug 2023 00:18:57 +0530 Subject: [PATCH] Update `Scrollable` on `ScrollBehaviour` change. (#131164) Fixes: #130793 --- .../flutter/lib/src/widgets/scrollable.dart | 6 + .../flutter/test/widgets/scrollable_test.dart | 107 ++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/packages/flutter/lib/src/widgets/scrollable.dart b/packages/flutter/lib/src/widgets/scrollable.dart index dfd3a80a67..0d7a24a857 100644 --- a/packages/flutter/lib/src/widgets/scrollable.dart +++ b/packages/flutter/lib/src/widgets/scrollable.dart @@ -632,6 +632,12 @@ class ScrollableState extends State with TickerProviderStateMixin, R } bool _shouldUpdatePosition(Scrollable oldWidget) { + if ((widget.scrollBehavior == null) != (oldWidget.scrollBehavior == null)) { + return true; + } + if (widget.scrollBehavior != null && oldWidget.scrollBehavior != null && widget.scrollBehavior!.shouldNotify(oldWidget.scrollBehavior!)) { + return true; + } ScrollPhysics? newPhysics = widget.physics ?? widget.scrollBehavior?.getScrollPhysics(context); ScrollPhysics? oldPhysics = oldWidget.physics ?? oldWidget.scrollBehavior?.getScrollPhysics(context); do { diff --git a/packages/flutter/test/widgets/scrollable_test.dart b/packages/flutter/test/widgets/scrollable_test.dart index 01ba9bccef..c5d5b5fd01 100644 --- a/packages/flutter/test/widgets/scrollable_test.dart +++ b/packages/flutter/test/widgets/scrollable_test.dart @@ -1356,6 +1356,113 @@ void main() { 'AlwaysScrollableScrollPhysics ClampingScrollPhysics RangeMaintainingScrollPhysics', ); }); + + testWidgets('dragDevices change updates widget', (WidgetTester tester) async { + bool enable = false; + + await tester.pumpWidget( + Builder( + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return MaterialApp( + home: Scaffold( + body: Scrollable( + scrollBehavior: const MaterialScrollBehavior().copyWith(dragDevices: { + if (enable) ui.PointerDeviceKind.mouse, + }), + viewportBuilder: (BuildContext context, ViewportOffset position) => Viewport( + offset: position, + slivers: const [ + SliverToBoxAdapter(child: SizedBox(height: 2000.0)), + ], + ), + ), + floatingActionButton: FloatingActionButton(onPressed: () { + setState(() { + enable = !enable; + }); + }), + ), + ); + }, + ); + }, + ) + ); + + // Gesture should not work. + TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true), kind: ui.PointerDeviceKind.mouse); + expect(getScrollOffset(tester), 0.0); + await gesture.moveBy(const Offset(0.0, -200)); + await tester.pumpAndSettle(); + expect(getScrollOffset(tester), 0.0); + + // Change state to include mouse pointer device. + await tester.tap(find.byType(FloatingActionButton)); + await tester.pump(); + + // Gesture should work after state change. + gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true), kind: ui.PointerDeviceKind.mouse); + expect(getScrollOffset(tester), 0.0); + await gesture.moveBy(const Offset(0.0, -200)); + await tester.pumpAndSettle(); + expect(getScrollOffset(tester), 200); + }); + + testWidgets('dragDevices change updates widget when oldWidget scrollBehavior is null', (WidgetTester tester) async { + ScrollBehavior? scrollBehavior; + + await tester.pumpWidget( + Builder( + builder: (BuildContext context) { + return StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return MaterialApp( + home: Scaffold( + body: Scrollable( + physics: const ScrollPhysics(), + scrollBehavior: scrollBehavior, + viewportBuilder: (BuildContext context, ViewportOffset position) => Viewport( + offset: position, + slivers: const [ + SliverToBoxAdapter(child: SizedBox(height: 2000.0)), + ], + ), + ), + floatingActionButton: FloatingActionButton(onPressed: () { + setState(() { + scrollBehavior = const MaterialScrollBehavior().copyWith(dragDevices: { + ui.PointerDeviceKind.mouse + }); + }); + }), + ), + ); + }, + ); + }, + ) + ); + + // Gesture should not work. + TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true), kind: ui.PointerDeviceKind.mouse); + expect(getScrollOffset(tester), 0.0); + await gesture.moveBy(const Offset(0.0, -200)); + await tester.pumpAndSettle(); + expect(getScrollOffset(tester), 0.0); + + // Change state to include mouse pointer device. + await tester.tap(find.byType(FloatingActionButton)); + await tester.pump(); + + // Gesture should work after state change. + gesture = await tester.startGesture(tester.getCenter(find.byType(Scrollable), warnIfMissed: true), kind: ui.PointerDeviceKind.mouse); + expect(getScrollOffset(tester), 0.0); + await gesture.moveBy(const Offset(0.0, -200)); + await tester.pumpAndSettle(); + expect(getScrollOffset(tester), 200); + }); } // ignore: must_be_immutable