Skip to content
Fetching contributors…
Cannot retrieve contributors at this time
127 lines (93 sloc) 3.76 KB
title lastmod publishdate author draft description tags youtube github
Flutter Drag and Drop Basics
2019-04-30 11:45:14 -0700
2019-04-30 11:45:14 -0700
Jeff Delaney
Learn how to create an interactive drag-and-drop UI in Flutter.

The following lesson will teach you how to build a simple drag-and-drop UI with the Draggable and DragTarget widgets. The demo app is a kid's game (ages 2 to 4) that requires the user to drag a fruit emoji 🍋 from the left column to the matching color on the right. If successfully dropped it will mark that item complete and the score will increase by one. The user can also reset the game at any time by pressing on the floating action button.

{{< vimeo 333404934 >}}

Initial Setup

In most cases, you will need your widgets organized within a StatefulWidget to render changes to the UI when certain drag/drop events take place.

{{< file "dart" "main.dart" >}} {{< highlight dart >}} class DragScreen extends StatefulWidget { DragScreen({Key key}) : super(key: key); createState() => ColorGameState(); }

class DragScreenState extends State {

@override Widget build(BuildContext context) { return Scaffold( body: Row( children: [ Column( // draggable widgets here ), Column( // droppable widgets here ) ], ), ); } } {{< /highlight >}}

How to Drag Widgets


There are three different visual states to consider when building a draggable widget.

  1. child - This is the child that is initially present.
  2. childWhenDragging - This is the widget that gets left behind after user starts dragging.
  3. feedback - This is the widget that moves or sticks to the user's finger. It may be identical to the child, or you may want to add some extra shadow to increase the realism of movement.

{{< figure src="img/draggable-parts.png" caption="The different parts of a Draggable widget after the user starts dragging" >}}

{{< file "dart" "main.dart" >}} {{< highlight dart >}} Draggable( data: // optional data to send to the drag target in next step, child: // widget feedback: // widget childWhenDragging: // widget ); {{< /highlight >}}

How to Drop Widgets


Now that we have a Draggable widget, we need to give it a "drop zone" using the DragTarget widget. It provides a builder function that gives you access to both the incoming and rejected data.

There are several functions that can be used to listen to the various drag/drop events:

  • builder constructs the UI for the DragTarget.
  • onWillAccept fires when the user starts hovering, it must return a boolean to decide whether or not the user can drop the widget here.
  • onAccept fires when the user drops and onWillAccept returns true.
  • onLeave fires if the user leaves without dropping or onWillAcccept returns false;

{{< file "dart" "main.dart" >}} {{< highlight dart >}} // Prop on StatefulWidget bool successfulDrop;

// Used inside build method DragTarget( builder: (BuildContext context, List incoming, List rejected) { if (successfulDrop == true) { return Text('Dropped!') } else { return Text('Empty dropzone'); } },

  onWillAccept: (data) => data == 'GOOD',

  onAccept: (data) {
    setState(() {
      successfulDrop = true;

  onLeave: (data) {


{{< /highlight >}}

You can’t perform that action at this time.