Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e1c902f
add optional dragAnchorStrategy to Draggable
prosac Dec 30, 2020
3b15dea
add optional dragAnchorStrategy to Draggable
prosac Dec 30, 2020
74284bd
fix naming of defaultDragAnchorStrategy in doc comment
prosac Jan 23, 2021
f713a41
Merge branch 'add_scaling_adaption_to_draggable' of github.com:prosac…
prosac Jan 23, 2021
b976e8a
fix reference in doc comment
prosac Feb 3, 2021
0cd2ad1
fix reference in doc comment
prosac Feb 3, 2021
f9f3161
Merge branch 'add_scaling_adaption_to_draggable' of github.com:prosac…
prosac Feb 5, 2021
dfde006
fix doc comments
prosac Feb 6, 2021
a32dd67
Merge branch 'master' into add_scaling_adaption_to_draggable
prosac Feb 6, 2021
90260df
Use suggested text for explaining the dragAnchorStrategy
prosac Feb 13, 2021
540f14f
Merge remote-tracking branch 'upstream/master' into add_scaling_adapt…
prosac Feb 13, 2021
b6d7e36
Merge branch 'master' into add_scaling_adaption_to_draggable
prosac Feb 16, 2021
8a801c6
fix typo and formatting
prosac Feb 16, 2021
200bc0c
improve comment
prosac Feb 16, 2021
6348fb8
improve comment
prosac Feb 16, 2021
fb368fb
Merge branch 'master' into add_scaling_adaption_to_draggable
prosac Feb 21, 2021
d1f2704
improve the way dragAnchorStrategy is introduced
prosac Feb 21, 2021
3f4f249
Improve @Deprecated info
prosac Feb 28, 2021
d940c06
Move dragAnchorStrategy conditional into _startDrag
prosac Feb 28, 2021
fdc7e2e
set version for deprecation
prosac Feb 28, 2021
3f63fe8
Update packages/flutter/lib/src/widgets/drag_target.dart
Mar 8, 2021
99a857b
Update packages/flutter/lib/src/widgets/drag_target.dart
Mar 8, 2021
d72ebdd
Update packages/flutter/lib/src/widgets/drag_target.dart
Mar 8, 2021
405c20a
change comment following suggestion
prosac Mar 8, 2021
d19f9d9
move declaration of dragStartPoint back to its original position
prosac Mar 8, 2021
3e8cdd8
Merge branch 'master' into add_scaling_adaption_to_draggable
prosac Mar 8, 2021
9088403
Merge branch 'add_scaling_adaption_to_draggable' of github.com:prosac…
prosac Mar 8, 2021
95c63da
Merge remote-tracking branch 'upstream/master' into add_scaling_adapt…
prosac Mar 11, 2021
38d5a33
update deprecation annotation
prosac Mar 11, 2021
738822c
Update packages/flutter/lib/src/widgets/drag_target.dart
Mar 11, 2021
4fb0ce6
Update packages/flutter/lib/src/widgets/drag_target.dart
Mar 11, 2021
55c6982
adapt manual test to use dragAnchorStrategy
prosac Mar 16, 2021
6df9504
Merge remote-tracking branch 'upstream/master' into add_scaling_adapt…
prosac Mar 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion dev/manual_tests/lib/drag_and_drop.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class ExampleDragSource extends StatelessWidget {

Offset feedbackOffset;
DragAnchor anchor;
DragAnchorStrategy dragAnchorStrategy;
if (!under) {
feedback = Transform(
transform: Matrix4.identity()
Expand All @@ -124,9 +125,11 @@ class ExampleDragSource extends StatelessWidget {
);
feedbackOffset = const Offset(0.0, -kFingerSize);
anchor = DragAnchor.pointer;
dragAnchorStrategy = pointerDragAnchorStrategy;
} else {
feedbackOffset = Offset.zero;
anchor = DragAnchor.child;
dragAnchorStrategy = childDragAnchorStrategy;
}

if (heavy) {
Expand All @@ -143,7 +146,7 @@ class ExampleDragSource extends StatelessWidget {
child: contents,
feedback: feedback,
feedbackOffset: feedbackOffset,
dragAnchor: anchor,
dragAnchorStrategy: dragAnchorStrategy,
);
}
}
Expand Down
59 changes: 50 additions & 9 deletions packages/flutter/lib/src/widgets/drag_target.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,24 @@ typedef DragTargetLeave<T> = void Function(T? data);
/// Used by [DragTarget.onMove].
typedef DragTargetMove<T> = void Function(DragTargetDetails<T> details);

/// Signature for the strategy that determines the drag start point.
///
/// Used for the built-in strategies switched via [DragAnchor] and the optinally
/// injectable [Draggable.dragAnchorStrategy]
typedef DragAnchorStrategy = Offset Function(Draggable<Object> draggable, BuildContext context, Offset position);

/// The default [DragAnchorStrategy] used when [Draggable.dragAnchor] is not set
/// or set to [DragAnchor.child]
Offset childDragAnchorStrategy(Draggable<Object> draggable, BuildContext context, Offset position) {
final RenderBox renderObject = context.findRenderObject()! as RenderBox;
return renderObject.globalToLocal(position);
}

/// The [DragAnchorStrategy] used when [Draggable.dragAnchor] set to
/// [DragAnchor.pointer]
Offset pointerDragAnchorStrategy(Draggable<Object> draggable, BuildContext context, Offset position) {
return Offset.zero;
}
/// Where the [Draggable] should be anchored during a drag.
enum DragAnchor {
/// Display the feedback anchored at the position of the original child. If
Expand Down Expand Up @@ -191,7 +209,12 @@ class Draggable<T extends Object> extends StatefulWidget {
this.axis,
this.childWhenDragging,
this.feedbackOffset = Offset.zero,
@Deprecated(
'Use dragAnchorStrategy instead. '
'This feature was deprecated after v2.1.0-10.0.pre.'
)
this.dragAnchor = DragAnchor.child,
this.dragAnchorStrategy,
this.affinity,
this.maxSimultaneousDrags,
this.onDragStarted,
Expand Down Expand Up @@ -263,8 +286,23 @@ class Draggable<T extends Object> extends StatefulWidget {
final Offset feedbackOffset;

/// Where this widget should be anchored during a drag.
///
/// This property is overridden by the [dragAnchorStrategy] if the latter is provided.
///
/// Defaults to [DragAnchor.child].
@Deprecated(
'Use dragAnchorStrategy instead. '
'This feature was deprecated after v2.1.0-10.0.pre.'
)
final DragAnchor dragAnchor;

/// A strategy that is used by this draggable to get the the anchor offset when it is dragged.
///
/// The anchor offset refers to the distance between the users' fingers and the [feedback] widget when this draggable is dragged.
///
/// Defaults to [childDragAnchorStrategy] if the [dragAnchor] is set to [DragAnchor.child] or [pointerDragAnchorStrategy] if the [dragAnchor] is set to [DragAnchor.pointer].
final DragAnchorStrategy? dragAnchorStrategy;

/// Whether the semantics of the [feedback] widget is ignored when building
/// the semantics tree.
///
Expand Down Expand Up @@ -308,7 +346,7 @@ class Draggable<T extends Object> extends StatefulWidget {
/// Called when the draggable starts being dragged.
final VoidCallback? onDragStarted;

/// Called when the draggable is being dragged.
/// Called when the draggable is dragged.
///
/// This function will only be called while this widget is still mounted to
/// the tree (i.e. [State.mounted] is true), and if this widget has actually moved.
Expand Down Expand Up @@ -487,14 +525,17 @@ class _DraggableState<T extends Object> extends State<Draggable<T>> {
if (widget.maxSimultaneousDrags != null && _activeCount >= widget.maxSimultaneousDrags!)
return null;
final Offset dragStartPoint;
switch (widget.dragAnchor) {
case DragAnchor.child:
final RenderBox renderObject = context.findRenderObject()! as RenderBox;
dragStartPoint = renderObject.globalToLocal(position);
break;
case DragAnchor.pointer:
dragStartPoint = Offset.zero;
break;
if (widget.dragAnchorStrategy == null) {
switch (widget.dragAnchor) {
case DragAnchor.child:
dragStartPoint = childDragAnchorStrategy(widget, context, position);
break;
case DragAnchor.pointer:
dragStartPoint = pointerDragAnchorStrategy(widget, context, position);
break;
}
} else {
dragStartPoint = widget.dragAnchorStrategy!(widget, context, position);
}
setState(() {
_activeCount += 1;
Expand Down
25 changes: 24 additions & 1 deletion packages/flutter/test/widgets/draggable_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2540,7 +2540,6 @@ void main() {
expect(find.text('Target'), findsOneWidget);
expect(onDragCompletedCalled, isFalse);


final Offset secondLocation = tester.getCenter(find.text('Target'));
await gesture.moveTo(secondLocation);
await tester.pump();
Expand Down Expand Up @@ -3019,6 +3018,30 @@ void main() {
semantics.dispose();
});

testWidgets('Drag and drop - when a dragAnchorStrategy is provided it gets called', (WidgetTester tester) async {
bool dragAnchorStrategyCalled = false;

await tester.pumpWidget(MaterialApp(
home: Column(
children: <Widget>[
Draggable<int>(
child: const Text('Source'),
feedback: const Text('Feedback'),
dragAnchorStrategy: (Draggable<Object> widget, BuildContext context, Offset position) {
dragAnchorStrategyCalled = true;
return const Offset(0, 0);
}
)
],
),
));

final Offset location = tester.getCenter(find.text('Source'));
await tester.startGesture(location, pointer: 7);

expect(dragAnchorStrategyCalled, true);
});

testWidgets('configurable Draggable hit test behavior', (WidgetTester tester) async {
const HitTestBehavior hitTestBehavior = HitTestBehavior.deferToChild;

Expand Down