How to move element anywhere inside parent container with drag and drop in Flutter?

2,799

Just ran into the same problem working on a drag-and-drop canvas in Flutter Web. I ended up working around this by inserting a GlobalKey for each of the draggable widgets and adjusting the placement offsets by accounting for the size of the containing renderbox (after waiting for the rendering to complete, via the addPostFrameCallback()). In order to facilitate precise placement, I used a Stack()/Positioned() and placed the Draggable() within this:

import 'package:flutter/material.dart';

class PositionedDraggableIcon extends StatefulWidget {
  final double top;
  final double left;

  PositionedDraggableIcon({Key key, this.top, this.left}) : super(key: key);

  @override
  _PositionedDraggableIconState createState() => _PositionedDraggableIconState();
}

class _PositionedDraggableIconState extends State<PositionedDraggableIcon> {
  GlobalKey _key = GlobalKey();
  double top, left;
  double xOff, yOff;

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
    top = widget.top;
    left = widget.left;
    super.initState();
  }

  void _getRenderOffsets() {
    final RenderBox renderBoxWidget = _key.currentContext.findRenderObject();
    final offset = renderBoxWidget.localToGlobal(Offset.zero);

    yOff = offset.dy - this.top;
    xOff = offset.dx - this.left;
  }

  void _afterLayout(_) {
    _getRenderOffsets();
  }

  @override
  Widget build(BuildContext context) {
    return Positioned(
      key: _key,
      top: top,
      left: left,
      child: Draggable(
        child: Icon(Icons.input),
        feedback: Icon(Icons.input),
        childWhenDragging: Container(),
        onDragEnd: (drag) {
          setState(() {
            top = drag.offset.dy - yOff;
            left = drag.offset.dx - xOff;
          });
        },
      ),
    );
  }
}

It's probably possible to do this with the widget context itself and avoid the GlobalKey, but this works well enough for me.

Share:
2,799
Peyman
Author by

Peyman

Updated on December 12, 2022

Comments

  • Peyman
    Peyman over 1 year

    I'm using the Draggable widget in Flutter, and I want to move my element anywhere inside a parent widget.

    I tried the dragtarget widget, but I couldn't set it to my parent widget. I also tried the onDraggableCanceled method of the Draggable widget for getting the offset, and applied it for the new offset of the element, but it gives me the offset from the device, not from the parent container.

    So, what is the right way of doing this?

    • jkdev
      jkdev almost 5 years
      Welcome to Stack Overflow! Could you please post the specific code that you are using?
  • Jhon Charles
    Jhon Charles about 2 years
    Is it possible to accomplish the same thing but using onDragUpdate?. I would like to avoid the element leaving the parent at all.