Unverified Commit 90c0e3e8 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Clarify documentation for DragAnchorStrategy. (#79160)

parent 0e2b40d8
......@@ -115,7 +115,6 @@ class ExampleDragSource extends StatelessWidget {
);
Offset feedbackOffset;
DragAnchor anchor;
DragAnchorStrategy dragAnchorStrategy;
if (!under) {
feedback = Transform(
......@@ -124,11 +123,9 @@ class ExampleDragSource extends StatelessWidget {
child: feedback,
);
feedbackOffset = const Offset(0.0, -kFingerSize);
anchor = DragAnchor.pointer;
dragAnchorStrategy = pointerDragAnchorStrategy;
} else {
feedbackOffset = Offset.zero;
anchor = DragAnchor.child;
dragAnchorStrategy = childDragAnchorStrategy;
}
......@@ -138,7 +135,7 @@ class ExampleDragSource extends StatelessWidget {
child: contents,
feedback: feedback,
feedbackOffset: feedbackOffset,
dragAnchor: anchor,
dragAnchorStrategy: dragAnchorStrategy,
);
} else {
return Draggable<Color>(
......
......@@ -53,7 +53,7 @@ typedef DraggableCanceledCallback = void Function(Velocity velocity, Offset offs
/// was dropped is available in the [DraggableDetails]. Also included in the
/// `details` is whether the draggable's [DragTarget] accepted it.
///
/// Used by [Draggable.onDragEnd]
/// Used by [Draggable.onDragEnd].
typedef DragEndCallback = void Function(DraggableDetails details);
/// Signature for when a [Draggable] leaves a [DragTarget].
......@@ -66,41 +66,83 @@ 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.
/// Signature for the strategy that determines the drag start point of a [Draggable].
///
/// Used for the built-in strategies switched via [DragAnchor] and the optimally
/// injectable [Draggable.dragAnchorStrategy]
/// Used by [Draggable.dragAnchorStrategy].
///
/// There are two built-in strategies:
///
/// * [childDragAnchorStrategy], which displays the feedback anchored at the
/// position of the original child.
///
/// * [pointerDragAnchorStrategy], which displays the feedback anchored at the
/// position of the touch that started the drag.
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]
/// Display the feedback anchored at the position of the original child.
///
/// If feedback is identical to the child, then this means the feedback will
/// exactly overlap the original child when the drag starts.
///
/// This is the default [DragAnchorStrategy] and replaces [DragAnchor.child].
///
/// See also:
///
/// * [DragAnchorStrategy], the typedef that this function implements.
/// * [Draggable.dragAnchorStrategy], for which this is a built-in value.
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]
/// Display the feedback anchored at the position of the touch that started
/// the drag.
///
/// If feedback is identical to the child, then this means the top left of the
/// feedback will be under the finger when the drag starts. This will likely not
/// exactly overlap the original child, e.g. if the child is big and the touch
/// was not centered. This mode is useful when the feedback is transformed so as
/// to move the feedback to the left by half its width, and up by half its width
/// plus the height of the finger, since then it appears as if putting the
/// finger down makes the touch feedback appear above the finger. (It feels
/// weird for it to appear offset from the original child if it's anchored to
/// the child and not the finger.)
///
/// This replaces [DragAnchor.pointer], which has been deprecated.
///
/// See also:
///
/// * [DragAnchorStrategy], the typedef that this function implements.
/// * [Draggable.dragAnchorStrategy], for which this is a built-in value.
Offset pointerDragAnchorStrategy(Draggable<Object> draggable, BuildContext context, Offset position) {
return Offset.zero;
}
/// Where the [Draggable] should be anchored during a drag.
///
/// This has been replaced by the more configurable [DragAnchorStrategy].
@Deprecated(
'Use dragAnchorStrategy instead. '
'This feature was deprecated after v2.1.0-10.0.pre.',
)
enum DragAnchor {
/// Display the feedback anchored at the position of the original child. If
/// feedback is identical to the child, then this means the feedback will
/// exactly overlap the original child when the drag starts.
/// Display the feedback anchored at the position of the original child.
///
/// Replaced by [childDragAnchorStrategy].
@Deprecated(
'Use childDragAnchorStrategy instead. '
'This feature was deprecated after v2.1.0-10.0.pre.',
)
child,
/// Display the feedback anchored at the position of the touch that started
/// the drag. If feedback is identical to the child, then this means the top
/// left of the feedback will be under the finger when the drag starts. This
/// will likely not exactly overlap the original child, e.g. if the child is
/// big and the touch was not centered. This mode is useful when the feedback
/// is transformed so as to move the feedback to the left by half its width,
/// and up by half its width plus the height of the finger, since then it
/// appears as if putting the finger down makes the touch feedback appear
/// above the finger. (It feels weird for it to appear offset from the
/// original child if it's anchored to the child and not the finger.)
/// the drag.
///
/// Replaced by [pointerDragAnchorStrategy].
@Deprecated(
'Use pointerDragAnchorStrategy instead. '
'This feature was deprecated after v2.1.0-10.0.pre.',
)
pointer,
}
......@@ -211,6 +253,8 @@ class Draggable<T extends Object> extends StatefulWidget {
this.feedbackOffset = Offset.zero,
@Deprecated(
'Use dragAnchorStrategy instead. '
'Replace "dragAnchor: DragAnchor.child" with "dragAnchorStrategy: childDragAnchorStrategy". '
'Replace "dragAnchor: DragAnchor.pointer" with "dragAnchorStrategy: pointerDragAnchorStrategy". '
'This feature was deprecated after v2.1.0-10.0.pre.',
)
this.dragAnchor = DragAnchor.child,
......@@ -296,11 +340,24 @@ class Draggable<T extends Object> extends StatefulWidget {
)
final DragAnchor dragAnchor;
/// A strategy that is used by this draggable to get the anchor offset when it is dragged.
/// A strategy that is used by this draggable to get 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.
/// 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].
/// This property's value is a function that implements [DragAnchorStrategy].
/// There are two built-in functions that can be used:
///
/// * [childDragAnchorStrategy], which displays the feedback anchored at the
/// position of the original child.
///
/// * [pointerDragAnchorStrategy], which displays the feedback anchored at the
/// position of the touch that started the drag.
///
/// Defaults to [childDragAnchorStrategy] if the deprecated [dragAnchor]
/// property is set to [DragAnchor.child], and [pointerDragAnchorStrategy] if
/// the [dragAnchor] is set to [DragAnchor.pointer].
final DragAnchorStrategy? dragAnchorStrategy;
/// Whether the semantics of the [feedback] widget is ignored when building
......@@ -435,7 +492,14 @@ class LongPressDraggable<T extends Object> extends Draggable<T> {
Axis? axis,
Widget? childWhenDragging,
Offset feedbackOffset = Offset.zero,
@Deprecated(
'Use dragAnchorStrategy instead. '
'Replace "dragAnchor: DragAnchor.child" with "dragAnchorStrategy: childDragAnchorStrategy". '
'Replace "dragAnchor: DragAnchor.pointer" with "dragAnchorStrategy: pointerDragAnchorStrategy". '
'This feature was deprecated after v2.1.0-10.0.pre.',
)
DragAnchor dragAnchor = DragAnchor.child,
DragAnchorStrategy? dragAnchorStrategy,
int? maxSimultaneousDrags,
VoidCallback? onDragStarted,
DragUpdateCallback? onDragUpdate,
......@@ -454,6 +518,7 @@ class LongPressDraggable<T extends Object> extends Draggable<T> {
childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor,
dragAnchorStrategy: dragAnchorStrategy,
maxSimultaneousDrags: maxSimultaneousDrags,
onDragStarted: onDragStarted,
onDragUpdate: onDragUpdate,
......
......@@ -3083,6 +3083,18 @@ void main() {
expect(tester.widget<MetaData>(find.byType(MetaData)).behavior, hitTestBehavior);
});
testWidgets('LongPressDraggable.dragAnchorStrategy', (WidgetTester tester) async {
const Widget widget1 = Placeholder(key: ValueKey<int>(1));
const Widget widget2 = Placeholder(key: ValueKey<int>(2));
Offset dummyStrategy(Draggable<Object> draggable, BuildContext context, Offset position) => Offset.zero;
expect(const LongPressDraggable<int>(child: widget1, feedback: widget2), isA<Draggable<int>>());
expect(const LongPressDraggable<int>(child: widget1, feedback: widget2).child, widget1);
expect(const LongPressDraggable<int>(child: widget1, feedback: widget2).feedback, widget2);
expect(const LongPressDraggable<int>(child: widget1, feedback: widget2, dragAnchor: DragAnchor.child).dragAnchor, DragAnchor.child);
expect(const LongPressDraggable<int>(child: widget1, feedback: widget2, dragAnchor: DragAnchor.pointer).dragAnchor, DragAnchor.pointer);
expect(LongPressDraggable<int>(child: widget1, feedback: widget2, dragAnchorStrategy: dummyStrategy).dragAnchorStrategy, dummyStrategy);
});
}
Future<void> _testLongPressDraggableHapticFeedback({ required WidgetTester tester, required bool hapticFeedbackOnStart, required int expectedHapticFeedbackCount }) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment