Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions doc/flame/inputs/drag_events.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,11 @@ position associated with this event.

### onDragCancel

The precise semantics when this event occurs is not clear, so we provide a default implementation
which simply converts this event into an `onDragEnd`.
This event is fired when the drag gesture is interrupted before it ends naturally, for example when
another gesture recognizer wins the gesture arena or a second pointer triggers a scale takeover.
Unlike `onDragEnd` it carries no velocity information. The default implementation simply resets the
drag state; override it and call `onDragEnd` yourself if you want a cancellation handled identically
to a natural drag end.


## Mixins
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,16 @@ mixin DragCallbacks on Component {

/// The drag was cancelled.
///
/// This is a very rare event, so we provide a default implementation that
/// converts it into an [onDragEnd] event.
/// Unlike [onDragEnd], a cancellation is not the natural end of a gesture: it
/// happens when the drag is interrupted (another recognizer wins the gesture
/// arena, a second pointer triggers a scale takeover, a system event, etc.),
/// so it carries no meaningful velocity. The default implementation only
/// resets the drag state. Override this and call [onDragEnd] yourself if you
/// want a cancellation handled identically to a natural drag end.
@mustCallSuper
void onDragCancel(DragCancelEvent event) => onDragEnd(event.toDragEnd());
void onDragCancel(DragCancelEvent event) {
_isDragged = false;
}

@override
@mustCallSuper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,41 @@ void main() {
);

expect(component.dragCancelEvent, equals(1));
expect(component.dragEndEvent, equals(1));
// onDragCancel no longer delegates to onDragEnd.
expect(component.dragEndEvent, equals(0));
expect(component.isDragged, isFalse);

dispatcher.onDragEnd(DragEndEvent(1, DragEndDetails()));
expect(component.dragCancelEvent, equals(1));
expect(component.dragEndEvent, equals(1));
expect(component.dragEndEvent, equals(0));
},
);

testWithFlameGame(
'onDragCancel resets isDragged without delegating to onDragEnd',
(game) async {
final component = DragCallbacksComponent()
..x = 10
..y = 10
..width = 10
..height = 10;
await game.ensureAdd(component);
final dispatcher = game.firstChild<MultiDragScaleDispatcher>()!;

dispatcher.onDragStart(
createDragStartEvents(
game: game,
localPosition: const Offset(12, 12),
globalPosition: const Offset(12, 12),
),
);
expect(component.isDragged, isTrue);

dispatcher.onDragCancel(DragCancelEvent(1));

expect(component.dragCancelEvent, equals(1));
expect(component.dragEndEvent, equals(0));
expect(component.isDragged, isFalse);
},
);

Expand Down Expand Up @@ -271,6 +300,7 @@ void main() {
var nDragStartCalled = 0;
var nDragUpdateCalled = 0;
var nDragEndCalled = 0;
var nDragCancelCalled = 0;
final game = FlameGame(
children: [
DragWithCallbacksComponent(
Expand All @@ -279,6 +309,7 @@ void main() {
onDragStart: (e) => nDragStartCalled++,
onDragUpdate: (e) => nDragUpdateCalled++,
onDragEnd: (e) => nDragEndCalled++,
onDragCancel: (e) => nDragCancelCalled++,
),
],
);
Expand Down Expand Up @@ -306,7 +337,9 @@ void main() {
await gesture.cancel();
await tester.pump(const Duration(seconds: 1));
expect(nDragStartCalled, 2);
expect(nDragEndCalled, 2);
expect(nDragCancelCalled, 1);
// The cancellation must not be reported as a drag end.
expect(nDragEndCalled, 1);
},
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,18 @@ class DragWithCallbacksComponent extends PositionComponent with DragCallbacks {
void Function(DragStartEvent)? onDragStart,
void Function(DragUpdateEvent)? onDragUpdate,
void Function(DragEndEvent)? onDragEnd,
void Function(DragCancelEvent)? onDragCancel,
super.position,
super.size,
}) : _onDragStart = onDragStart,
_onDragUpdate = onDragUpdate,
_onDragEnd = onDragEnd;
_onDragEnd = onDragEnd,
_onDragCancel = onDragCancel;

final void Function(DragStartEvent)? _onDragStart;
final void Function(DragUpdateEvent)? _onDragUpdate;
final void Function(DragEndEvent)? _onDragEnd;
final void Function(DragCancelEvent)? _onDragCancel;

@override
void onDragStart(DragStartEvent event) {
Expand All @@ -129,6 +132,12 @@ class DragWithCallbacksComponent extends PositionComponent with DragCallbacks {
super.onDragEnd(event);
return _onDragEnd?.call(event);
}

@override
void onDragCancel(DragCancelEvent event) {
super.onDragCancel(event);
return _onDragCancel?.call(event);
}
}

class ScaleWithCallbacksComponent extends PositionComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,13 @@ void main() {
);

expect(component.dragCancelEvent, equals(1));
expect(component.dragEndEvent, equals(1));
// onDragCancel no longer delegates to onDragEnd.
expect(component.dragEndEvent, equals(0));
expect(component.isDragged, isFalse);

dispatcher.onDragEnd(DragEndEvent(1, DragEndDetails()));
expect(component.dragCancelEvent, equals(1));
expect(component.dragEndEvent, equals(1));
expect(component.dragEndEvent, equals(0));
},
);

Expand Down Expand Up @@ -188,13 +189,13 @@ void main() {

dispatcher.onDragCancel(DragCancelEvent(1));
expect(component.dragCancelEvent, equals(1));
// onDragCancel delegates to onDragEnd internally
expect(component.dragEndEvent, equals(1));
// onDragCancel no longer delegates to onDragEnd.
expect(component.dragEndEvent, equals(0));
expect(component.isDragged, isFalse);

// record removed after cancel; subsequent end for same pointer is a no-op
dispatcher.onDragEnd(DragEndEvent(1, DragEndDetails()));
expect(component.dragEndEvent, equals(1));
expect(component.dragEndEvent, equals(0));
},
);

Expand Down
Loading