Skip to content

Generalize gesture details that concerns cartesian positioning in a common interface #101530

Description

@mateusfccp

Use case

When generalizing over gesture details, we have to be specific about which details class we are using. This is not a big problem, but we could use of some generalization to make more abstract code.

For example, I have code similar to this in a production app:

// Currently, I have not how to guarantee that `DetailsType` is going to be a gesture details object
class GestureDetailsWithAdditionalData<DetailsType, T extends Object> {
  const LayerGestureDetails({
    required this.details,
    required this.data,
  });

  final DetailsType details;
  final T data;
}

ValueChanged<DetailsType> gesturerFor<DetailsType>({
  required ValueChanged<GestureDetailsWithAdditionalData<DetailsType, Object>>? Function(Layer) gestureFunction,
  required Offset Function(T) getLocalPosition,
}) {
  return (DetailsType details) {
    final layer = getLayer(...);
    final localPosition = getLocalPosition(details);
    // Do something with localPosition
    final gesture = gestureFunction(layer);
  };
}

// Usage
gesturerFor<TapDownDetails>(
  gestureFunction: (layer) => layer.onTapUp,
  getLocalPosition: (details) => details.localPosition,
);

If they implemented a common abstraction, the code could be simplified and made safer:

// Now I guarantee that details is something expected
class GestureDetailsWithAdditionalData<DetailsType extends PositionRelatedGestureDetails, T extends Object> {
  const LayerGestureDetails({
    required this.details,
    required this.data,
  });

  final DetailsType details;
  final T data;
}

ValueChanged<DetailsType> gesturerFor<DetailsType>(ValueChanged<GestureDetailsWithAdditionalData<DetailsType, Object>>? Function(Layer) gestureFunction) {
  return (DetailsType details) {
    final layer = getLayer(...);
    // I now can use details.localPosition directly
    final gesture = gestureFunction(layer);
  };
}

// Usage now guarantees that the returned function works on details
gesturerFor<TapDownDetails>(gestureFunction: (layer) => layer.onTapUp);

Proposal

Almost all gesture details related to cartesian positioning have in common a localPosition and globalPosition.

  • DragDownDetails
  • DragStartDetails
  • DragUpdateDetails
  • ForcePressDetails
  • LongPressDownDetails
  • LongPressEndDetails
  • LongPressMoveUpdateDetails
  • LongPressStartDetails
  • SerialTapDownDetails
  • SerialTapUpDetails
  • TapDownDetails
  • TapUpDetails

It would be nice and, as far as I can tell, a non-breaking change to make a common interface for them:

abstract class PositionRelatedGestureDetails {
  /// Documentation...
  Offset get localPosition;

  /// Documentation...
  Offset get globalPosition;
}

Scale gestures also have similar properties (focalPoint and localFocalPoint), but I am not sure if they should be included somehow in this generalization.

Metadata

Metadata

Assignees

Labels

P3Issues that are less important to the Flutter projectc: proposalA detailed proposal for a change to Flutterf: gesturesflutter/packages/flutter/gestures repository.frameworkflutter/packages/flutter repository. See also f: labels.team-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions