Do we have onTapDown and Drag functionality in flutter?

111

One solution could be to wrap your layout with GestureDetector and "guess" the position of your elements to then know where the drag ends.

EDIT: Adding a real check on the target position to make it more robust thanks to @GoodSp33d comment:

class DragView extends StatefulWidget {
  const DragView({Key? key}) : super(key: key);

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

GlobalKey orangeContainerKey = GlobalKey();
GlobalKey greenContainerKey = GlobalKey();

class _DragViewState extends State<DragView> {
  Rect? getGlobalPaintBounds(GlobalKey element) {
    final renderObject = element.currentContext!.findRenderObject();
    var translation = renderObject?.getTransformTo(null).getTranslation();
    if (translation != null && renderObject?.paintBounds != null) {
      return renderObject?.paintBounds
          .shift(Offset(translation.x, translation.y));
    } else {
      return null;
    }
  }

  bool isInRect(double x, double y, Rect? rect) {
    if (rect != null)
      return x >= rect.left &&
          x <= rect.right &&
          y <= rect.bottom &&
          y >= rect.top;
    return false;
  }

  @override
  Widget build(BuildContext context) {
    double _cursorX = 0;
    double _cursorY = 0;

    return GestureDetector(
      onHorizontalDragUpdate: (details) {
        _cursorX = details.globalPosition.dx;
        _cursorY = details.globalPosition.dy;
      },
      onHorizontalDragEnd: (details) {
        if (isInRect(
            _cursorX, _cursorY, getGlobalPaintBounds(orangeContainerKey)))
          print("Orange");
        if (isInRect(
            _cursorX, _cursorY, getGlobalPaintBounds(greenContainerKey)))
          print("Green");
      },
      child: Row(
        children: [
          Expanded(
            child: Container(key: greenContainerKey, color: Colors.green),
          ),
          Expanded(
            child: Container(key: orangeContainerKey, color: Colors.orange),
          ),
        ],
      ),
    );
  }
}

Second edit moving the detection to the onDragUpdate and checks to make it happens only on rect changes:

    GlobalKey? currentObject;

      onHorizontalDragUpdate: (details) {
        _cursorX = details.globalPosition.dx;
        _cursorY = details.globalPosition.dy;
        if (isInRect(
            _cursorX, _cursorY, getGlobalPaintBounds(orangeContainerKey))) {
          if (currentObject == null || currentObject != orangeContainerKey) {
            print("Orange");
            currentObject = orangeContainerKey;
          }
        }
        if (isInRect(_cursorX, _cursorY,
            getGlobalPaintBounds(greenContainerKey))) if (currentObject ==
                null ||
            currentObject != greenContainerKey) {
          print("Green");
          currentObject = greenContainerKey;
        }
      },

Share:
111
Alvey
Author by

Alvey

Updated on December 31, 2022

Comments

  • Alvey
    Alvey over 1 year

    I have a simple usecase which is some how super tricky for a beginner in flutter.

    I need these values returned for the scenario explained below


    There are 2 containers in a row (green and orange) enter image description here

    1. OnTapDown on green container it should return ‘Green’ (this is straight forward and done)
    2. Without lifting the finger off the screen, I drag my finger over the Orange container and I need that to return ‘Orange’


    How do I solve this?

    • Alvey
      Alvey over 2 years
      I have tried using GestureDetector 'onTapDown' and also tried using Listener with these functions 'onPointerDown', 'onPointerMove' still not able to figure how to execute this
    • Yeasin Sheikh
      Yeasin Sheikh over 2 years
    • Colin Lazarini
      Colin Lazarini over 2 years
      Dont forget to upvote and set mark it as resolved ;)
  • GoodSp33d
    GoodSp33d over 2 years
    You can assign keys to both green and orange containers and detect if touch point is in the container or not instead to make it more robust.
  • Alvey
    Alvey over 2 years
    Hey, thanks for the quick reply I tried this, and it returns 'Orange' after Drag Ends right, but i need the value to be returned as soon as it reaches orange
  • Colin Lazarini
    Colin Lazarini over 2 years
    Then you need to calculate the position in the dragUpdate method and not end, but also add a check that if it is still the same container to not print or do anything.
  • Alvey
    Alvey over 2 years
    @Wapazz it works when i updated in drag update :) thanks
  • Colin Lazarini
    Colin Lazarini over 2 years
    I added to the answer to make it not refresh everytime