mirror of
https://github.com/flutter/flutter
synced 2024-08-24 18:36:03 +00:00
Add position data to OnDragEnd
callback (#140378)
This PR adds localPosition/globalPosition data to the `DragEndDetails` argument of the `onDragEnd` callback.
This commit is contained in:
parent
ed02cf2f4a
commit
fa71e8029b
|
@ -214,11 +214,14 @@ class DragEndDetails {
|
|||
DragEndDetails({
|
||||
this.velocity = Velocity.zero,
|
||||
this.primaryVelocity,
|
||||
this.globalPosition = Offset.zero,
|
||||
Offset? localPosition,
|
||||
}) : assert(
|
||||
primaryVelocity == null
|
||||
|| (primaryVelocity == velocity.pixelsPerSecond.dx && velocity.pixelsPerSecond.dy == 0)
|
||||
|| (primaryVelocity == velocity.pixelsPerSecond.dy && velocity.pixelsPerSecond.dx == 0),
|
||||
);
|
||||
),
|
||||
localPosition = localPosition ?? globalPosition;
|
||||
|
||||
/// The velocity the pointer was moving when it stopped contacting the screen.
|
||||
///
|
||||
|
@ -237,6 +240,23 @@ class DragEndDetails {
|
|||
/// Defaults to null if not specified in the constructor.
|
||||
final double? primaryVelocity;
|
||||
|
||||
/// The global position the pointer is located at when the drag
|
||||
/// gesture has been completed.
|
||||
///
|
||||
/// Defaults to the origin if not specified in the constructor.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [localPosition], which is the [globalPosition] transformed to the
|
||||
/// coordinate space of the event receiver.
|
||||
final Offset globalPosition;
|
||||
|
||||
/// The local position in the coordinate system of the event receiver when
|
||||
/// the drag gesture has been completed.
|
||||
///
|
||||
/// Defaults to [globalPosition] if not specified in the constructor.
|
||||
final Offset localPosition;
|
||||
|
||||
@override
|
||||
String toString() => '${objectRuntimeType(this, 'DragEndDetails')}($velocity)';
|
||||
}
|
||||
|
|
|
@ -276,6 +276,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
_DragState _state = _DragState.ready;
|
||||
late OffsetPair _initialPosition;
|
||||
late OffsetPair _pendingDragOffset;
|
||||
late OffsetPair _finalPosition;
|
||||
Duration? _lastPendingEventTimestamp;
|
||||
|
||||
/// When asserts are enabled, returns the last tracked pending event timestamp
|
||||
|
@ -351,6 +352,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
if (_state == _DragState.ready) {
|
||||
_state = _DragState.possible;
|
||||
_initialPosition = OffsetPair(global: event.position, local: event.localPosition);
|
||||
_finalPosition = _initialPosition;
|
||||
_pendingDragOffset = OffsetPair.zero;
|
||||
_globalDistanceMoved = 0.0;
|
||||
_lastPendingEventTimestamp = event.timeStamp;
|
||||
|
@ -418,6 +420,7 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
final Offset localDelta = (event is PointerMoveEvent) ? event.localDelta : (event as PointerPanZoomUpdateEvent).localPanDelta;
|
||||
final Offset position = (event is PointerMoveEvent) ? event.position : (event.position + (event as PointerPanZoomUpdateEvent).pan);
|
||||
final Offset localPosition = (event is PointerMoveEvent) ? event.localPosition : (event.localPosition + (event as PointerPanZoomUpdateEvent).localPan);
|
||||
_finalPosition = OffsetPair(local: localPosition, global: position);
|
||||
if (_state == _DragState.accepted) {
|
||||
_checkUpdate(
|
||||
sourceTimeStamp: event.timeStamp,
|
||||
|
@ -600,7 +603,11 @@ abstract class DragGestureRecognizer extends OneSequenceGestureRecognizer {
|
|||
? () => '$estimate; fling at ${details!.velocity}.'
|
||||
: () => '$estimate; judged to not be a fling.';
|
||||
}
|
||||
details ??= DragEndDetails(primaryVelocity: 0.0);
|
||||
details ??= DragEndDetails(
|
||||
primaryVelocity: 0.0,
|
||||
globalPosition: _finalPosition.global,
|
||||
localPosition: _finalPosition.local,
|
||||
);
|
||||
|
||||
invokeCallback<void>('onEnd', () => onEnd!(details!), debugReport: debugReport);
|
||||
}
|
||||
|
@ -660,6 +667,8 @@ class VerticalDragGestureRecognizer extends DragGestureRecognizer {
|
|||
return DragEndDetails(
|
||||
velocity: Velocity(pixelsPerSecond: Offset(0, dy)),
|
||||
primaryVelocity: dy,
|
||||
globalPosition: _finalPosition.global,
|
||||
localPosition: _finalPosition.local,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -715,6 +724,8 @@ class HorizontalDragGestureRecognizer extends DragGestureRecognizer {
|
|||
return DragEndDetails(
|
||||
velocity: Velocity(pixelsPerSecond: Offset(dx, 0)),
|
||||
primaryVelocity: dx,
|
||||
globalPosition: _finalPosition.global,
|
||||
localPosition: _finalPosition.local,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -765,7 +776,11 @@ class PanGestureRecognizer extends DragGestureRecognizer {
|
|||
}
|
||||
final Velocity velocity = Velocity(pixelsPerSecond: estimate.pixelsPerSecond)
|
||||
.clampMagnitude(minFlingVelocity ?? kMinFlingVelocity, maxFlingVelocity ?? kMaxFlingVelocity);
|
||||
return DragEndDetails(velocity: velocity);
|
||||
return DragEndDetails(
|
||||
velocity: velocity,
|
||||
globalPosition: _finalPosition.global,
|
||||
localPosition: _finalPosition.local,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -125,6 +125,40 @@ void main() {
|
|||
expect(didEndPan, isTrue);
|
||||
});
|
||||
|
||||
testWidgets('DragEndDetails returns the last known position', (WidgetTester tester) async {
|
||||
Offset updateOffset = const Offset(10.0, 10.0);
|
||||
const EdgeInsets paddingOffset = EdgeInsets.all(10.0);
|
||||
Offset? endOffset;
|
||||
Offset? globalEndOffset;
|
||||
|
||||
await tester.pumpWidget(
|
||||
Padding(
|
||||
padding: paddingOffset,
|
||||
child: GestureDetector(
|
||||
onPanStart: (DragStartDetails details) {
|
||||
},
|
||||
onPanUpdate: (DragUpdateDetails details) {
|
||||
updateOffset += details.delta;
|
||||
},
|
||||
onPanEnd: (DragEndDetails details) {
|
||||
endOffset = details.localPosition;
|
||||
globalEndOffset = details.globalPosition;
|
||||
},
|
||||
child: Container(
|
||||
color: const Color(0xFF00FF00),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
await tester.dragFrom(const Offset(20.0, 20.0), const Offset(30.0, 40.0));
|
||||
|
||||
expect(endOffset, isNotNull);
|
||||
expect(updateOffset, endOffset);
|
||||
// Make sure details.globalPosition works correctly.
|
||||
expect(Offset(endOffset!.dx + paddingOffset.left, endOffset!.dy + paddingOffset.top), globalEndOffset);
|
||||
});
|
||||
|
||||
group('Tap', () {
|
||||
final ButtonVariant buttonVariant = ButtonVariant(
|
||||
values: <int>[kPrimaryButton, kSecondaryButton, kTertiaryButton],
|
||||
|
|
Loading…
Reference in a new issue