Maintain the same layout constraints for item in the ReorderableList during dragging as before dragging. (#147863)

Fixes #147419
This commit is contained in:
yim 2024-05-15 04:52:59 +08:00 committed by GitHub
parent 4ecc1b092b
commit e2ef38d19f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 65 additions and 5 deletions

View File

@ -11,6 +11,7 @@ import 'basic.dart';
import 'debug.dart'; import 'debug.dart';
import 'framework.dart'; import 'framework.dart';
import 'inherited_theme.dart'; import 'inherited_theme.dart';
import 'layout_builder.dart';
import 'localizations.dart'; import 'localizations.dart';
import 'media_query.dart'; import 'media_query.dart';
import 'overlay.dart'; import 'overlay.dart';
@ -1083,6 +1084,8 @@ class _ReorderableItemState extends State<_ReorderableItem> {
} }
} }
bool _dragging = false; bool _dragging = false;
BoxConstraints? get childLayoutConstraints => _childLayoutConstraints;
BoxConstraints? _childLayoutConstraints;
@override @override
void initState() { void initState() {
@ -1114,10 +1117,13 @@ class _ReorderableItemState extends State<_ReorderableItem> {
return SizedBox.fromSize(size: size); return SizedBox.fromSize(size: size);
} }
_listState._registerItem(this); _listState._registerItem(this);
return Transform( return LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
transform: Matrix4.translationValues(offset.dx, offset.dy, 0.0), _childLayoutConstraints = constraints;
child: widget.child, return Transform(
); transform: Matrix4.translationValues(offset.dx, offset.dy, 0.0),
child: widget.child,
);
});
} }
@override @override
@ -1337,6 +1343,7 @@ class _DragInfo extends Drag {
dragOffset = itemRenderBox.globalToLocal(initialPosition); dragOffset = itemRenderBox.globalToLocal(initialPosition);
itemSize = item.context.size!; itemSize = item.context.size!;
itemExtent = _sizeExtent(itemSize, scrollDirection); itemExtent = _sizeExtent(itemSize, scrollDirection);
itemLayoutConstraints = item.childLayoutConstraints!;
scrollable = Scrollable.of(item.context); scrollable = Scrollable.of(item.context);
} }
@ -1354,6 +1361,7 @@ class _DragInfo extends Drag {
late Offset dragPosition; late Offset dragPosition;
late Offset dragOffset; late Offset dragOffset;
late Size itemSize; late Size itemSize;
late BoxConstraints itemLayoutConstraints;
late double itemExtent; late double itemExtent;
late CapturedThemes capturedThemes; late CapturedThemes capturedThemes;
ScrollableState? scrollable; ScrollableState? scrollable;
@ -1411,6 +1419,7 @@ class _DragInfo extends Drag {
listState: listState, listState: listState,
index: index, index: index,
size: itemSize, size: itemSize,
constraints: itemLayoutConstraints,
animation: _proxyAnimation!, animation: _proxyAnimation!,
position: dragPosition - dragOffset - _overlayOrigin(context), position: dragPosition - dragOffset - _overlayOrigin(context),
proxyDecorator: proxyDecorator, proxyDecorator: proxyDecorator,
@ -1433,6 +1442,7 @@ class _DragItemProxy extends StatelessWidget {
required this.child, required this.child,
required this.position, required this.position,
required this.size, required this.size,
required this.constraints,
required this.animation, required this.animation,
required this.proxyDecorator, required this.proxyDecorator,
}); });
@ -1442,6 +1452,7 @@ class _DragItemProxy extends StatelessWidget {
final Widget child; final Widget child;
final Offset position; final Offset position;
final Size size; final Size size;
final BoxConstraints constraints;
final AnimationController animation; final AnimationController animation;
final ReorderItemProxyDecorator? proxyDecorator; final ReorderItemProxyDecorator? proxyDecorator;
@ -1468,7 +1479,14 @@ class _DragItemProxy extends StatelessWidget {
child: SizedBox( child: SizedBox(
width: size.width, width: size.width,
height: size.height, 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,
),
), ),
); );
}, },

View File

@ -1528,6 +1528,48 @@ void main() {
await testFor(prototypeItem: const SizedBox(height: 100, width: 100, child: Text('prototype'))); await testFor(prototypeItem: const SizedBox(height: 100, width: 100, child: Text('prototype')));
await testFor(itemExtent: 100); await testFor(itemExtent: 100);
}); });
testWidgets('The item being dragged will not be affected by layout constraints.', (WidgetTester tester) async {
final Map<int, BoxConstraints> itemLayoutConstraints = <int, BoxConstraints>{};
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverReorderableList(
itemBuilder: (BuildContext context, int index) {
return LayoutBuilder(
key: ValueKey<int>(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<int, BoxConstraints> preDragLayoutConstraints = Map<int, BoxConstraints>.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 { class TestList extends StatelessWidget {