https://medium.com/flutter-community/a-deep-dive-into-draggable-and-dragtarget-in-flutter-487919f6f1e4
This article is the sixth in a series of articles which take an in-depth look at Flutter’s built in widgets.
- ListView/ScrollPhysics
- TextFields
- FloatingActionButtons
- Hero Widget
- Transform Widget
DragTarget.
Exploring Draggable and DragTargets
DragTargets then dive into details of customizing them.
Draggable
A “Draggable” makes a widget movable around the screen. Let’s use a chess knight as our example.
The code for this is relatively straightforward:
Draggable(
child: WhiteKnight(
size: 90.0,
),
feedback: WhiteKnight(
size: 90.0,
),
childWhenDragging: Container(),
),
Draggable widget:
- child parameter is the widget that will be displayed when the draggable is stationary
- feedback is the widget that will be displayed when the widget is being dragged.
- when the widget is being dragged.
Container in its place.
Let’s customize the widget
feedback parameter.
In the example below, we change the feedback parameter to a white bishop. Now, when the widget is not being dragged, a white knight is shown however as you start dragging, our bishop is shown.
Draggable(
child: WhiteKnight(
size: 90.0,
),
feedback: WhiteBishop(
size: 90.0,
),
childWhenDragging: Container(),
),
Result of the above code:
child as the widget is being dragged.
We’ll display a white rook when the widget is being dragged:
Draggable(
child: WhiteKnight(
size: 90.0,
),
feedback: WhiteBishop(
size: 90.0,
),
childWhenDragging: WhiteRook(
size: 90.0,
),
),
This becomes:
Restricting motion for Draggables
axis parameter helps us restrict motion in one dimension only.
Axis.horizontal makes the feedback widget on,y move in the horizontal axis.
Draggable(
axis: Axis.horizontal,
child: WhiteKnight(
size: 90.0,
),
feedback: WhiteBishop(
size: 90.0,
),
childWhenDragging: Container(),
),
Similarly, we also have Axis.vertical for vertical movement.
Adding data to Draggable
DragTargets.
Considering our example, if we were to have multiple chess pieces, each piece would need to have unique data associated with it. Pieces would need properties such as color (White, Black) and type (ie: Rook, Bishop, Knight).
DragTarget.
We will take a look at this more in-depth in the DragTarget section.
Draggable(
child: WhiteKnight(
size: 90.0,
),
feedback: WhiteKnight(
size: 90.0,
),
childWhenDragging: Container(),
data: [
"White",
"Knight"
],
),
Callbacks
draggable widget supplies callbacks for actions on the widget.
These callbacks are:
onDragStarted : This is called when a drag is started on a widget.
DragTarget is in the next section.
DragTarget or is rejected, this callback is fired.
DragTarget
provides a destination for the draggable.
a square box on the chessboard is a drag target.
DragTarget.
The code for this example goes:
bool accepted = false;
DragTarget(builder: (context, List<String> candidateData, rejectedData) {
return accepted ? WhiteKnight(size: 90.0,) : Container();
}, onWillAccept: (data) {
return true;
}, onAccept: (data) {
accepted = true;
},),
is surrounded by a black colored container which is not shown in the code for brevity.
DragTarget in more detail.
Draggable.
Builder
DragTarget or is dropped onto it.
rejectedData.
DragTarget.
DragTarget at moment it is not accepted.
At this point, they are not dropped onto it yet.
DragTarget know what to accept?
onWillAccept
Draggable data for us to decide whether to accept or reject it.
Draggables.
For example if our Draggable is:
Draggable(
data: "Knight",
// ...
),
then we can do:
DragTarget(
// ...
onWillAccept: (data) {
if(data == "Knight") {
return true;
} else {
return false;
}
},
),
Draggable if the data is “Knight”.
DragTarget.
onAccept
onAccept is called.
DragTarget.
onLeave
DragTarget and leaves without being dropped.
A Demo
Let’s create a simple demo app where the user is given a number and they are required to sort it as either “even” or “odd’. Depending on the choice, we will then display a message stating whether the choice is correct or wrong.
Source code:
A few more things
Draggable customisations
Draggable gives us a few more customizations.
Draggable with two or more pointers and hence we can have multiple feedback on screen. For instance if the user is using a second finger to drag a child while one drag is already progress, we receive two feedback widgets at the same time.
draggable can be dragged at one time.
property also lets us set the offset of the feedback widget that displays on the screen.
Common error: DragTarget not accepting data
List<String>.
builder: (context, List<String> candidateData, rejectedData) {
// ...
}
This solves a few type errors that occasionally comes up when passing data.
DragTarget
DragTargets.
here.
Note: There is an update coming up to the package which includes a better architecture for the package, more boards, etc.
chess_vectors_flutter package for the examples on this article.