From e2ef38d19f4e35de41832b88e32b2ae10e670ecd Mon Sep 17 00:00:00 2001 From: yim Date: Wed, 15 May 2024 04:52:59 +0800 Subject: [PATCH] Maintain the same layout constraints for item in the ReorderableList during dragging as before dragging. (#147863) Fixes #147419 --- .../lib/src/widgets/reorderable_list.dart | 28 ++++++++++--- .../test/widgets/reorderable_list_test.dart | 42 +++++++++++++++++++ 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/packages/flutter/lib/src/widgets/reorderable_list.dart b/packages/flutter/lib/src/widgets/reorderable_list.dart index 598e055db8..de54b2e4a7 100644 --- a/packages/flutter/lib/src/widgets/reorderable_list.dart +++ b/packages/flutter/lib/src/widgets/reorderable_list.dart @@ -11,6 +11,7 @@ import 'basic.dart'; import 'debug.dart'; import 'framework.dart'; import 'inherited_theme.dart'; +import 'layout_builder.dart'; import 'localizations.dart'; import 'media_query.dart'; import 'overlay.dart'; @@ -1083,6 +1084,8 @@ class _ReorderableItemState extends State<_ReorderableItem> { } } bool _dragging = false; + BoxConstraints? get childLayoutConstraints => _childLayoutConstraints; + BoxConstraints? _childLayoutConstraints; @override void initState() { @@ -1114,10 +1117,13 @@ class _ReorderableItemState extends State<_ReorderableItem> { return SizedBox.fromSize(size: size); } _listState._registerItem(this); - return Transform( - transform: Matrix4.translationValues(offset.dx, offset.dy, 0.0), - child: widget.child, - ); + return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) { + _childLayoutConstraints = constraints; + return Transform( + transform: Matrix4.translationValues(offset.dx, offset.dy, 0.0), + child: widget.child, + ); + }); } @override @@ -1337,6 +1343,7 @@ class _DragInfo extends Drag { dragOffset = itemRenderBox.globalToLocal(initialPosition); itemSize = item.context.size!; itemExtent = _sizeExtent(itemSize, scrollDirection); + itemLayoutConstraints = item.childLayoutConstraints!; scrollable = Scrollable.of(item.context); } @@ -1354,6 +1361,7 @@ class _DragInfo extends Drag { late Offset dragPosition; late Offset dragOffset; late Size itemSize; + late BoxConstraints itemLayoutConstraints; late double itemExtent; late CapturedThemes capturedThemes; ScrollableState? scrollable; @@ -1411,6 +1419,7 @@ class _DragInfo extends Drag { listState: listState, index: index, size: itemSize, + constraints: itemLayoutConstraints, animation: _proxyAnimation!, position: dragPosition - dragOffset - _overlayOrigin(context), proxyDecorator: proxyDecorator, @@ -1433,6 +1442,7 @@ class _DragItemProxy extends StatelessWidget { required this.child, required this.position, required this.size, + required this.constraints, required this.animation, required this.proxyDecorator, }); @@ -1442,6 +1452,7 @@ class _DragItemProxy extends StatelessWidget { final Widget child; final Offset position; final Size size; + final BoxConstraints constraints; final AnimationController animation; final ReorderItemProxyDecorator? proxyDecorator; @@ -1468,7 +1479,14 @@ class _DragItemProxy extends StatelessWidget { child: SizedBox( width: size.width, height: size.height, - child: child, + child: OverflowBox( + minWidth: constraints.minWidth, + minHeight: constraints.minHeight, + maxWidth: constraints.maxWidth, + maxHeight: constraints.maxHeight, + alignment: listState._scrollDirection == Axis.horizontal ? Alignment.centerLeft : Alignment.topCenter, + child: child, + ), ), ); }, diff --git a/packages/flutter/test/widgets/reorderable_list_test.dart b/packages/flutter/test/widgets/reorderable_list_test.dart index 802d97aed5..cd1c25c529 100644 --- a/packages/flutter/test/widgets/reorderable_list_test.dart +++ b/packages/flutter/test/widgets/reorderable_list_test.dart @@ -1528,6 +1528,48 @@ void main() { await testFor(prototypeItem: const SizedBox(height: 100, width: 100, child: Text('prototype'))); await testFor(itemExtent: 100); }); + + testWidgets('The item being dragged will not be affected by layout constraints.', (WidgetTester tester) async { + final Map itemLayoutConstraints = {}; + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: CustomScrollView( + slivers: [ + SliverReorderableList( + itemBuilder: (BuildContext context, int index) { + return LayoutBuilder( + key: ValueKey(index), + builder: (BuildContext context, BoxConstraints constraints) { + itemLayoutConstraints[index] = constraints; + return SizedBox( + height: 100, + child: ReorderableDragStartListener( + index: index, + child: Text('$index'), + ), + ); + } + ); + }, + itemCount: 5, + onReorder: (int fromIndex, int toIndex) {}, + ), + ], + ), + ), + ), + ); + final Map preDragLayoutConstraints = Map.of(itemLayoutConstraints); + itemLayoutConstraints.clear(); + final TestGesture drag = await tester.startGesture(tester.getCenter(find.text('0'))); + await tester.pump(kLongPressTimeout); + await drag.moveBy(const Offset(0, 20)); + await tester.pump(); + expect(itemLayoutConstraints, preDragLayoutConstraints); + await drag.up(); + await tester.pumpAndSettle(); + }); } class TestList extends StatelessWidget {