Skip to content

Commit d5bee36

Browse files
authored
Fix an reorderable list animation issue:"Reversed ReorderableListView drop animation moves item one row higher than it should #110949" (#111027)
1 parent 6206fbf commit d5bee36

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

packages/flutter/lib/src/widgets/reorderable_list.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -758,9 +758,11 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke
758758

759759
void _dragEnd(_DragInfo item) {
760760
setState(() {
761-
if (_insertIndex! < widget.itemCount - 1) {
762-
// Find the location of the item we want to insert before
761+
if (_insertIndex == item.index) {
763762
_finalDropPosition = _itemOffsetAt(_insertIndex! + (_reverse ? 1 : 0));
763+
} else if (_insertIndex! < widget.itemCount - 1) {
764+
// Find the location of the item we want to insert before
765+
_finalDropPosition = _itemOffsetAt(_insertIndex!);
764766
} else {
765767
// Inserting into the last spot on the list. If it's the only spot, put
766768
// it back where it was. Otherwise, grab the second to last and move

packages/flutter/test/widgets/reorderable_list_test.dart

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,57 @@ void main() {
521521
expect(tester.takeException(), isNull);
522522
});
523523

524+
testWidgets('SliverReorderableList - properly animates the drop in a reversed list', (WidgetTester tester) async {
525+
// Regression test for https://github.com/flutter/flutter/issues/110949
526+
final List<int> items = List<int>.generate(8, (int index) => index);
527+
528+
Future<void> pressDragRelease(Offset start, Offset delta) async {
529+
final TestGesture drag = await tester.startGesture(start);
530+
await tester.pump(kPressTimeout);
531+
await drag.moveBy(delta);
532+
await tester.pumpAndSettle();
533+
await drag.up();
534+
await tester.pump();
535+
}
536+
537+
// The TestList is 800x600 SliverReorderableList with 8 items 800x100 each.
538+
// Each item has a text widget with 'item $index' that can be moved by a
539+
// press and drag gesture. For this test we are reversing the order so
540+
// the first item is at the bottom.
541+
await tester.pumpWidget(TestList(items: items, reverse: true));
542+
543+
expect(tester.getTopLeft(find.text('item 0')), const Offset(0, 500));
544+
expect(tester.getTopLeft(find.text('item 2')), const Offset(0, 300));
545+
546+
// Drag item 0 up and insert it between item 1 and item 2. It should
547+
// smoothly animate.
548+
await pressDragRelease(tester.getCenter(find.text('item 0')), const Offset(0, -50));
549+
expect(tester.getTopLeft(find.text('item 0')), const Offset(0, 450));
550+
expect(tester.getTopLeft(find.text('item 1')), const Offset(0, 500));
551+
expect(tester.getTopLeft(find.text('item 2')), const Offset(0, 300));
552+
553+
// After the first several frames we should be moving closer to the final position,
554+
// not further away as was the case with the original bug.
555+
await tester.pump(const Duration(milliseconds: 10));
556+
expect(tester.getTopLeft(find.text('item 0')).dy, lessThan(450));
557+
expect(tester.getTopLeft(find.text('item 0')).dy, greaterThan(400));
558+
559+
// Sample the middle (don't use exact values as it depends on the internal
560+
// curve being used).
561+
await tester.pump(const Duration(milliseconds: 125));
562+
expect(tester.getTopLeft(find.text('item 0')).dy, lessThan(450));
563+
expect(tester.getTopLeft(find.text('item 0')).dy, greaterThan(400));
564+
565+
// Sample the end of the animation.
566+
await tester.pump(const Duration(milliseconds: 100));
567+
expect(tester.getTopLeft(find.text('item 0')).dy, lessThan(450));
568+
expect(tester.getTopLeft(find.text('item 0')).dy, greaterThan(400));
569+
570+
// Wait for it to finish, it should be back to the original position
571+
await tester.pumpAndSettle();
572+
expect(tester.getTopLeft(find.text('item 0')), const Offset(0, 400));
573+
});
574+
524575
testWidgets('SliverReorderableList - properly animates the drop at starting position in a reversed list', (WidgetTester tester) async {
525576
// Regression test for https://github.com/flutter/flutter/issues/84625
526577
final List<int> items = List<int>.generate(8, (int index) => index);

0 commit comments

Comments
 (0)