diff --git a/packages/flutter/lib/src/widgets/reorderable_list.dart b/packages/flutter/lib/src/widgets/reorderable_list.dart index b20bf7116b7..f46b3470ec8 100644 --- a/packages/flutter/lib/src/widgets/reorderable_list.dart +++ b/packages/flutter/lib/src/widgets/reorderable_list.dart @@ -1270,11 +1270,13 @@ class ReorderableDragStartListener extends StatelessWidget { } void _startDragging(BuildContext context, PointerDownEvent event) { + final DeviceGestureSettings? gestureSettings = MediaQuery.maybeOf(context)?.gestureSettings; final SliverReorderableListState? list = SliverReorderableList.maybeOf(context); list?.startItemDragReorder( index: index, event: event, - recognizer: createRecognizer(), + recognizer: createRecognizer() + ..gestureSettings = gestureSettings, ); } } diff --git a/packages/flutter/test/widgets/reorderable_list_test.dart b/packages/flutter/test/widgets/reorderable_list_test.dart index 65ece9da210..3d4a2a2b819 100644 --- a/packages/flutter/test/widgets/reorderable_list_test.dart +++ b/packages/flutter/test/widgets/reorderable_list_test.dart @@ -7,6 +7,63 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { + testWidgets('SliverReorderableList works well when having gestureSettings', (WidgetTester tester) async { + // Regression test for https://github.com/flutter/flutter/issues/103404 + const int itemCount = 5; + int onReorderCallCount = 0; + final List items = List.generate(itemCount, (int index) => index); + + void handleReorder(int fromIndex, int toIndex) { + onReorderCallCount += 1; + if (toIndex > fromIndex) { + toIndex -= 1; + } + items.insert(toIndex, items.removeAt(fromIndex)); + } + // The list has five elements of height 100 + await tester.pumpWidget( + MaterialApp( + home: MediaQuery( + data: const MediaQueryData(gestureSettings: DeviceGestureSettings(touchSlop: 8.0)), + child: CustomScrollView( + slivers: [ + SliverReorderableList( + itemCount: itemCount, + itemBuilder: (BuildContext context, int index) { + return SizedBox( + key: ValueKey(items[index]), + height: 100, + child: ReorderableDragStartListener( + index: index, + child: Text('item ${items[index]}'), + ), + ); + }, + onReorder: handleReorder, + ) + ], + ), + ), + ), + ); + + // Start gesture on first item + final TestGesture drag = await tester.startGesture(tester.getCenter(find.text('item 0'))); + await tester.pump(kPressTimeout); + + // Drag a little bit to make `ImmediateMultiDragGestureRecognizer` compete with `VerticalDragGestureRecognizer` + await drag.moveBy(const Offset(0, 10)); + await tester.pump(); + // Drag enough to move down the first item + await drag.moveBy(const Offset(0, 40)); + await tester.pump(); + await drag.up(); + await tester.pumpAndSettle(); + + expect(onReorderCallCount, 1); + expect(items, orderedEquals([1, 0, 2, 3, 4])); + }); + // Regression test for https://github.com/flutter/flutter/issues/100451 testWidgets('SliverReorderableList.builder respects findChildIndexCallback', (WidgetTester tester) async { bool finderCalled = false;