Alvey
Alvey

Reputation: 53

Do we have onTapDown and Drag functionality in flutter?

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?

Upvotes: 1

Views: 795

Answers (1)

Colin Lazarini
Colin Lazarini

Reputation: 947

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;
        }
      },

Upvotes: 1

Related Questions