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 { ...@@ -115,7 +115,6 @@ class ExampleDragSource extends StatelessWidget {
); );
Offset feedbackOffset; Offset feedbackOffset;
DragAnchor anchor;
DragAnchorStrategy dragAnchorStrategy; DragAnchorStrategy dragAnchorStrategy;
if (!under) { if (!under) {
feedback = Transform( feedback = Transform(
...@@ -124,11 +123,9 @@ class ExampleDragSource extends StatelessWidget { ...@@ -124,11 +123,9 @@ class ExampleDragSource extends StatelessWidget {
child: feedback, child: feedback,
); );
feedbackOffset = const Offset(0.0, -kFingerSize); feedbackOffset = const Offset(0.0, -kFingerSize);
anchor = DragAnchor.pointer;
dragAnchorStrategy = pointerDragAnchorStrategy; dragAnchorStrategy = pointerDragAnchorStrategy;
} else { } else {
feedbackOffset = Offset.zero; feedbackOffset = Offset.zero;
anchor = DragAnchor.child;
dragAnchorStrategy = childDragAnchorStrategy; dragAnchorStrategy = childDragAnchorStrategy;
} }
...@@ -138,7 +135,7 @@ class ExampleDragSource extends StatelessWidget { ...@@ -138,7 +135,7 @@ class ExampleDragSource extends StatelessWidget {
child: contents, child: contents,
feedback: feedback, feedback: feedback,
feedbackOffset: feedbackOffset, feedbackOffset: feedbackOffset,
dragAnchor: anchor, dragAnchorStrategy: dragAnchorStrategy,
); );
} else { } else {
return Draggable<Color>( return Draggable<Color>(
......
...@@ -53,7 +53,7 @@ typedef DraggableCanceledCallback = void Function(Velocity velocity, Offset offs ...@@ -53,7 +53,7 @@ typedef DraggableCanceledCallback = void Function(Velocity velocity, Offset offs
/// was dropped is available in the [DraggableDetails]. Also included in the /// was dropped is available in the [DraggableDetails]. Also included in the
/// `details` is whether the draggable's [DragTarget] accepted it. /// `details` is whether the draggable's [DragTarget] accepted it.
/// ///
/// Used by [Draggable.onDragEnd] /// Used by [Draggable.onDragEnd].
typedef DragEndCallback = void Function(DraggableDetails details); typedef DragEndCallback = void Function(DraggableDetails details);
/// Signature for when a [Draggable] leaves a [DragTarget]. /// Signature for when a [Draggable] leaves a [DragTarget].
...@@ -66,41 +66,83 @@ typedef DragTargetLeave<T> = void Function(T? data); ...@@ -66,41 +66,83 @@ typedef DragTargetLeave<T> = void Function(T? data);
/// Used by [DragTarget.onMove]. /// Used by [DragTarget.onMove].
typedef DragTargetMove<T> = void Function(DragTargetDetails<T> details); 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 /// Used by [Draggable.dragAnchorStrategy].
/// injectable [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); typedef DragAnchorStrategy = Offset Function(Draggable<Object> draggable, BuildContext context, Offset position);
/// The default [DragAnchorStrategy] used when [Draggable.dragAnchor] is not set /// Display the feedback anchored at the position of the original child.
/// or set to [DragAnchor.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) { Offset childDragAnchorStrategy(Draggable<Object> draggable, BuildContext context, Offset position) {
final RenderBox renderObject = context.findRenderObject()! as RenderBox; final RenderBox renderObject = context.findRenderObject()! as RenderBox;
return renderObject.globalToLocal(position); return renderObject.globalToLocal(position);
} }
/// The [DragAnchorStrategy] used when [Draggable.dragAnchor] set to /// Display the feedback anchored at the position of the touch that started
/// [DragAnchor.pointer] /// 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) { Offset pointerDragAnchorStrategy(Draggable<Object> draggable, BuildContext context, Offset position) {
return Offset.zero; return Offset.zero;
} }
/// Where the [Draggable] should be anchored during a drag. /// 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 { enum DragAnchor {
/// Display the feedback anchored at the position of the original child. If /// Display the feedback anchored at the position of the original child.
/// feedback is identical to the child, then this means the feedback will ///
/// exactly overlap the original child when the drag starts. /// Replaced by [childDragAnchorStrategy].
@Deprecated(
'Use childDragAnchorStrategy instead. '
'This feature was deprecated after v2.1.0-10.0.pre.',
)
child, child,
/// Display the feedback anchored at the position of the touch that started /// 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 /// the drag.
/// 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 /// Replaced by [pointerDragAnchorStrategy].
/// big and the touch was not centered. This mode is useful when the feedback @Deprecated(
/// is transformed so as to move the feedback to the left by half its width, 'Use pointerDragAnchorStrategy instead. '
/// and up by half its width plus the height of the finger, since then it 'This feature was deprecated after v2.1.0-10.0.pre.',
/// 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.)
pointer, pointer,
} }
...@@ -211,6 +253,8 @@ class Draggable<T extends Object> extends StatefulWidget { ...@@ -211,6 +253,8 @@ class Draggable<T extends Object> extends StatefulWidget {
this.feedbackOffset = Offset.zero, this.feedbackOffset = Offset.zero,
@Deprecated( @Deprecated(
'Use dragAnchorStrategy instead. ' '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 feature was deprecated after v2.1.0-10.0.pre.',
) )
this.dragAnchor = DragAnchor.child, this.dragAnchor = DragAnchor.child,
...@@ -296,11 +340,24 @@ class Draggable<T extends Object> extends StatefulWidget { ...@@ -296,11 +340,24 @@ class Draggable<T extends Object> extends StatefulWidget {
) )
final DragAnchor dragAnchor; 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.
///
/// 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.
/// ///
/// The anchor offset refers to the distance between the users' fingers and the [feedback] widget when this draggable is dragged. /// * [pointerDragAnchorStrategy], which displays the feedback anchored at the
/// position of the touch that started the drag.
/// ///
/// Defaults to [childDragAnchorStrategy] if the [dragAnchor] is set to [DragAnchor.child] or [pointerDragAnchorStrategy] if the [dragAnchor] is set to [DragAnchor.pointer]. /// 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; final DragAnchorStrategy? dragAnchorStrategy;
/// Whether the semantics of the [feedback] widget is ignored when building /// Whether the semantics of the [feedback] widget is ignored when building
...@@ -435,7 +492,14 @@ class LongPressDraggable<T extends Object> extends Draggable<T> { ...@@ -435,7 +492,14 @@ class LongPressDraggable<T extends Object> extends Draggable<T> {
Axis? axis, Axis? axis,
Widget? childWhenDragging, Widget? childWhenDragging,
Offset feedbackOffset = Offset.zero, 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, DragAnchor dragAnchor = DragAnchor.child,
DragAnchorStrategy? dragAnchorStrategy,
int? maxSimultaneousDrags, int? maxSimultaneousDrags,
VoidCallback? onDragStarted, VoidCallback? onDragStarted,
DragUpdateCallback? onDragUpdate, DragUpdateCallback? onDragUpdate,
...@@ -454,6 +518,7 @@ class LongPressDraggable<T extends Object> extends Draggable<T> { ...@@ -454,6 +518,7 @@ class LongPressDraggable<T extends Object> extends Draggable<T> {
childWhenDragging: childWhenDragging, childWhenDragging: childWhenDragging,
feedbackOffset: feedbackOffset, feedbackOffset: feedbackOffset,
dragAnchor: dragAnchor, dragAnchor: dragAnchor,
dragAnchorStrategy: dragAnchorStrategy,
maxSimultaneousDrags: maxSimultaneousDrags, maxSimultaneousDrags: maxSimultaneousDrags,
onDragStarted: onDragStarted, onDragStarted: onDragStarted,
onDragUpdate: onDragUpdate, onDragUpdate: onDragUpdate,
......
...@@ -3083,6 +3083,18 @@ void main() { ...@@ -3083,6 +3083,18 @@ void main() {
expect(tester.widget<MetaData>(find.byType(MetaData)).behavior, hitTestBehavior); 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 { 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