Skip to content

fix: onDragCancel should not delegate to onDragEnd by default #3926

@spydon

Description

@spydon

Problem

DragCallbacks.onDragCancel currently delegates to onDragEnd by default:

void onDragCancel(DragCancelEvent event) => onDragEnd(event.toDragEnd());

These two events are semantically different:

  • onDragEnd: the user lifted their finger naturally; carries velocity info for fling detection.
  • onDragCancel: the gesture was interrupted (another recognizer won the arena, a second finger caused a scale takeover, a system event, etc.); no meaningful velocity.

Calling onDragEnd from onDragCancel conflates the two. A drag-to-dismiss component would incorrectly "apply the action" when the drag was actually cancelled. Calls from cancel always produce zero velocity in DragEndDetails, which can cause subtle bugs.

The comment in the source calls cancellations "very rare", but with MultiDragScaleDispatcher (PR #3782) this is no longer true: every two-finger pinch gesture cancels the individual pointer drags.

Proposed fix

  • onDragCancel should reset isDragged directly (the same way onDragEnd does) without forwarding to onDragEnd.
  • Users who want identical handling can override onDragCancel to call onDragEnd themselves.

Impact

This is a breaking change: existing code that relies on onDragCancel triggering onDragEnd will need to be updated.

Related to #1938.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions