diff --git a/packages/flutter/lib/src/material/reorderable_list.dart b/packages/flutter/lib/src/material/reorderable_list.dart index c12d4cf053..809f1c0536 100644 --- a/packages/flutter/lib/src/material/reorderable_list.dart +++ b/packages/flutter/lib/src/material/reorderable_list.dart @@ -574,6 +574,11 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T ); break; } + + // If the reorderable list only has one child element, reordering + // should not be allowed. + final bool hasMoreThanOneChildElement = widget.children.length > 1; + return SingleChildScrollView( scrollDirection: widget.scrollDirection, padding: widget.padding, @@ -581,10 +586,10 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T reverse: widget.reverse, child: _buildContainerForScrollDirection( children: [ - if (widget.reverse) _wrap(finalDropArea, widget.children.length, constraints), + if (widget.reverse && hasMoreThanOneChildElement) _wrap(finalDropArea, widget.children.length, constraints), if (widget.header != null) widget.header, for (int i = 0; i < widget.children.length; i += 1) _wrap(widget.children[i], i, constraints), - if (!widget.reverse) _wrap(finalDropArea, widget.children.length, constraints), + if (!widget.reverse && hasMoreThanOneChildElement) _wrap(finalDropArea, widget.children.length, constraints), ], ), ); diff --git a/packages/flutter/test/material/reorderable_list_test.dart b/packages/flutter/test/material/reorderable_list_test.dart index 96a20739e7..831ec52438 100644 --- a/packages/flutter/test/material/reorderable_list_test.dart +++ b/packages/flutter/test/material/reorderable_list_test.dart @@ -56,6 +56,33 @@ void main() { }); group('in vertical mode', () { + testWidgets('reorder is not triggered when children length is less or equals to 1', (WidgetTester tester) async { + bool onReorderWasCalled = false; + final List currentListItems = listItems.take(1).toList(); + final ReorderableListView reorderableListView = ReorderableListView( + header: const Text('Header'), + children: currentListItems.map(listItemToWidget).toList(), + scrollDirection: Axis.vertical, + onReorder: (_, __) => onReorderWasCalled = true, + ); + final List currentOriginalListItems = originalListItems.take(1).toList(); + await tester.pumpWidget(MaterialApp( + home: SizedBox( + height: itemHeight * 10, + child: reorderableListView, + ), + )); + expect(currentListItems, orderedEquals(currentOriginalListItems)); + final TestGesture drag = await tester.startGesture(tester.getCenter(find.text('Item 1'))); + await tester.pump(kLongPressTimeout + kPressTimeout); + expect(currentListItems, orderedEquals(currentOriginalListItems)); + await drag.moveTo(tester.getBottomLeft(find.text('Item 1')) * 2); + expect(currentListItems, orderedEquals(currentOriginalListItems)); + await drag.up(); + expect(onReorderWasCalled, false); + expect(currentListItems, orderedEquals(['Item 1'])); + }); + testWidgets('reorders its contents only when a drag finishes', (WidgetTester tester) async { await tester.pumpWidget(build()); expect(listItems, orderedEquals(originalListItems)); @@ -547,6 +574,33 @@ void main() { }); group('in horizontal mode', () { + testWidgets('reorder is not triggered when children length is less or equals to 1', (WidgetTester tester) async { + bool onReorderWasCalled = false; + final List currentListItems = listItems.take(1).toList(); + final ReorderableListView reorderableListView = ReorderableListView( + header: const Text('Header'), + children: currentListItems.map(listItemToWidget).toList(), + scrollDirection: Axis.horizontal, + onReorder: (_, __) => onReorderWasCalled = true, + ); + final List currentOriginalListItems = originalListItems.take(1).toList(); + await tester.pumpWidget(MaterialApp( + home: SizedBox( + height: itemHeight * 10, + child: reorderableListView, + ), + )); + expect(currentListItems, orderedEquals(currentOriginalListItems)); + final TestGesture drag = await tester.startGesture(tester.getCenter(find.text('Item 1'))); + await tester.pump(kLongPressTimeout + kPressTimeout); + expect(currentListItems, orderedEquals(currentOriginalListItems)); + await drag.moveTo(tester.getBottomLeft(find.text('Item 1')) * 2); + expect(currentListItems, orderedEquals(currentOriginalListItems)); + await drag.up(); + expect(onReorderWasCalled, false); + expect(currentListItems, orderedEquals(['Item 1'])); + }); + testWidgets('allows reordering from the very top to the very bottom', (WidgetTester tester) async { await tester.pumpWidget(build(scrollDirection: Axis.horizontal)); expect(listItems, orderedEquals(originalListItems));