Implementing Drag and Drop

684 views
Skip to first unread message

Joel Trottier-Hébert

unread,
May 2, 2016, 3:32:58 PM5/2/16
to Flutter Dev
Is there an example somewhere of Draggable usage? I’m trying to reorder MaterialList’s ListItem's reorder with drag and drop.

I don’t know if my ListItem or my List widget should implement Draggable (if it should be implemented at all). When I have the ListItem implementing it, the analyzer yells that it can’t implement it, but when I have the List widget implementing it, I have like 9 overrides to fill, and most of them don’t seem to make sense to me.

Basically, I want to take the Shopping list example, and make it drag-and-drop re-orderable, just to give you some context.

Kris Giesing

unread,
May 2, 2016, 4:56:01 PM5/2/16
to Joel Trottier-Hébert, Flutter Dev
Hi Joel,

I don't think there's a good example of drag-and-drop right now. I've filed this issue to track adding one: https://github.com/flutter/flutter/issues/3673

To answer your specific question: Rather than extending Draggable, just wrap your ShoppingListItems with a Draggable in the build() function for _ShoppingListState. The draggable takes a feedback widget in addition to the child, to indicate what should be shown while a drag is happening:

        children: config.products.map((Product product) {
          return new Draggable(
            child: new ShoppingListItem(
              product: product,
              inCart: _shoppingCart.contains(product),
              onCartChanged: _handleCartChanged
            ),
            feedback: ...
          );
        })

The feedback can be whatever you want, more or less. (If you use a material widget as drag feedback, you do need to be careful to provide a Material widget as a wrapper; the default overlay where the drag feedback happens doesn't use a Material.)

Handling the reorder and the drop is a little more complicated. Take a look at DragTarget to see the API for handling a drop; you can use this to track where the drop occurred and reorder the list of Products in response. If you want to handle sliding the neighboring items apart as the track happens, you'd probably also use DragTarget in the process, but you'd need some animation support to render the items sliding around. I'd have to think a while longer to know how that part would work; maybe someone else on this list has some thoughts there?

Hope this helps,

- Kris

--
You received this message because you are subscribed to the Google Groups "Flutter Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flutter-dev...@googlegroups.com.
To post to this group, send email to flutt...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/flutter-dev/1d66534a-2f5c-46e8-ad03-5ba8adbfd820%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ian Hickson

unread,
May 2, 2016, 5:52:46 PM5/2/16
to Kris Giesing, Joel Trottier-Hébert, Flutter Dev
There's a manual test in the dev/manual_tests directory that I use to test Draggable, if you just want something to crib from. It's not up to our standards as a real example, but it might do for now.


Joel Trottier-Hébert

unread,
May 2, 2016, 10:07:18 PM5/2/16
to Ian Hickson, Kris Giesing, Flutter Dev
Thanks to both of you. I'll check that out!

Joel Trottier-Hébert

unread,
May 2, 2016, 11:05:54 PM5/2/16
to Flutter Dev
Alright, so I tried what you said, now I could use a Text widget as the feedback. Now I tried to do something a bit more complex, specifically, use the ListItem as the feedback item.

I tried this:

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(title: new Text('Shopping List')),
        body: new MaterialList(
            type: MaterialListType.oneLineWithAvatar,
            children: config.products.map((Product product) {
              var rowItem = new ShoppingListItem(
                  product: product,
                  inCart: _shoppingCart.contains(product),
                  onCartChanged: _handleCartChanged);

              return new Draggable(
                  child: new Material(child: rowItem),
                  feedback: rowItem);
            })));
  }
}

But I get the error you mentioned before : I need to use a Material widget as the wrapper. I couldn't get it to work using a new Material(child: rowItem) or I even tried something a little facy, wrapping it into a new Opacity(..., content: rowItem) but that didn't work either.

I believe the error I was getting was something about the widget I was using doesn't specify a finite width constraint. I figured I could wrap the rowItem in a Dialog and it worked. However it wasn't pretty. What kind of Wrapper can I use, that would wrap the child widget and give it a width constraint?

Thanks.

Ian Hickson

unread,
May 3, 2016, 1:04:39 AM5/3/16
to Joel Trottier-Hébert, Flutter Dev
A Container can give it a size constraint (height and width properties). If you want the list item to have the exact size it had when you started dragging it, that's a little trickier right now... feel free to file a bug (https://github.com/flutter/flutter/issues/new) with that use case if you'd like a simple way to handle that case.

Reply all
Reply to author
Forward
0 new messages