flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
165.61k stars 27.34k forks source link

Add property to `DragTarget` to change appearance when a `Draggable` is dragged but not necessarily near the `DragTarget` #119404

Open bmitc opened 1 year ago

bmitc commented 1 year ago

Use case

Right now, the DragTarget class has the relevant properties:

However, these two only get initiated when a Draggable moves "within" or "over" the drag target. This is okay, but it is somewhat mobile focused, where there is not much room for a lot of drag targets. On desktop and in certain applications, one might imagine there being several DragTargets for a given Draggable.

For example, consider a board game where a player picks up, i.e. drags, a pawn represented by a Draggable. In such a case, the application might want to highlight the various options on the board, represented by DragTargets, where the pawn can be placed, before the pawn is moved within or over the acceptable places.

Right now, this has to be handled implicitly outside of the Draggable and DragTarget classes, as far as I can tell.

An image to hopefully communicate a potential use case:

image

The user initiates a drag on the red checker that gets highlighted with green, and then the various acceptable drop locations get highlighted in blue, before the checker is placed over the acceptable squares.

Proposal

The proposal is to either modify the existing properties to be more generic, passing through both the draggable type and a flag whether the draggable is within or over the drag target or coordinates, or add a new property (the more backwards compatible way) to configure the behavior for any draggable being dragged anywhere within the window or application (in the case of a multi-window application).

It isn't entirely clear to me what the name should be because the names are actually already relevant. I think onWillAccept is the perfect name, but unfortunately the current implementation only triggers when the data is dragged over the drag target. Maybe onWillAcceptDraggable or onWillAcceptGlobal or onWillAcceptAny?

(Apologies for perhaps imprecise language. I am new to Flutter and Dart, so I probably am abusing some nomenclature surrounding properties.)

darshankawar commented 1 year ago

@bmitc Thanks for the report. Can you check this issue and see if it resembles your case ?

bmitc commented 1 year ago

Hi @darshankawar. Thank you for the response, but unfortunately, no it doesn't. That issue is specifically discussing when onMove and onLeave get triggered. Right now, the cursor position entering and leaving the DragTarget's widget boundary is what triggers the behavior. That issue is asking for the option of using the Draggable's widget boundary. I have added a video and example code to that issue to demonstrate. (Note that onMove is poorly named. It should probably be named onEnter.)

The issue I filed here is much more generic. There should be an easy way for DragTarget's to be notified of any drag happening (maybe with some settable filters) such that they may change their appearance accordingly. This is shown in the image, and note that I do mention several times that there should be an event even when the DragTarget and Draggable are not near each other.

An example video of the behavior to complete my original image description:

https://user-images.githubusercontent.com/65685447/215430044-2b63685d-4366-4661-a0db-ff22c416f0a8.mp4

This can be accomplished right now by using, in this case, onDragStarted and onDraggableCanceled inside the Draggable, but it is done implicitly and ad-hoc. The appearance change of the DragTarget should be handled by the DragTarget and not the by the Draggable.

There are three main scenarios that a DragTarget should be notified of and be able to handle:

  1. A drag started anywhere in the application
  2. A Draggable's widget boundary has intersected the DragTarget's widget boundary
  3. The cursor dragging a Draggable has intersected the DragTarget's widget boundary

(3) is the only one explicitly supported right now. (2) is requested by the issue you linked. (1) is what I am requesting in this issue.

And please note that by "anywhere in the application" I mean even in another window. Flutter has been adding multi-window support, and thus, DragTarget's in one window should be able to be notified (via some new property as proposed here) that a Draggable has started to be dragged, even if that starts in another window within the same application.

darshankawar commented 1 year ago

Thanks for the detailed update.

flutter-triage-bot[bot] commented 4 months ago

The triaged-desktop label is irrelevant if there is no team-desktop label or fyi-desktop label.