2

I'm implementing a Drawing App in Flutter. I'm referring this tutorial but Somehow I got stuck by an

issue

Brief: As you can see I have two container. One for Drawing and below one for 'Draw Above'. But points drawn its beyond.I want user can draw within the upper container. So my question is - How to cancel Gesture detection, if it goes beyond a particular container's bounds?

Code snippet:

final GestureDetector paintGesture = GestureDetector(
  onPanUpdate: (DragUpdateDetails details) {
    setState(() {
      RenderBox object = context.findRenderObject();
      Offset _localPosition = object.localToGlobal(details.globalPosition);
      _points = new List.from(_points)..add(_localPosition);
    });
  },
  onPanEnd: (DragEndDetails details) {
      _points.add(null);
  },
  child: sketchArea,
);

final Container sketchArea = Container(
  //margin: EdgeInsets.all(1.0),
  //alignment: Alignment.topLeft,
  color: Colors.white,
  child: new CustomPaint(
    painter: new Signature(points: _points),
    size: Size.infinite,
  ),
);

Scaffold:

return new Scaffold(
  body: Container(
    child: Column(
      children: <Widget>[
        Expanded(
          child:  paintGesture,
        ),
        Expanded(
          child: Center(
            child: Container(
              child: Text(
                _selectedInput,
                style: TextStyle(
                  color: Colors.black,
                  fontSize: 40.0,
                ),
              ),
            ),
          ),
        ),
      ],
    ),
  ),
);
Amir Khan
  • 1,318
  • 1
  • 14
  • 39
  • can you post your full code? – TruongSinh Mar 04 '19 at 13:18
  • @TruongSinh, I've already posted my main code snippet. As SO recommended not to confuse users by posting long post, make it clear and understandable. I know I've to add some check on these below but don't know how to apply in dart - `RenderBox object = context.findRenderObject(); Offset _localPosition = object.localToGlobal(details.globalPosition); _points = new List.from(_points)..add(_localPosition);` – Amir Khan Mar 04 '19 at 15:32
  • @TruongSinh I've updated my post. Please check. – Amir Khan Mar 05 '19 at 04:16

1 Answers1

0

I used the solution by vovohost from this post to get the coordinates of my Container :

Extension :

extension GlobalKeyExtension on GlobalKey {
  Rect get globalPaintBounds {
    final renderObject = 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;
    }
  }
}

Usage :

final containerKey = GlobalKey();
Rect get containerRect => containerKey.globalPaintBounds;

Container(
  key: containerKey,
  width: 100,
  height: 50,
)

void printWidgetPosition() {
  print('absolute coordinates on screen: ${containerRect}');
}

Once I got the coordinates, I had to use this method to return an Offset within bounds of my Container :

Offset _offsetInBox(Offset globalOffset) {
  // Y coordinate
  double nearestY = 0;
  if (globalOffset.dy >= containerRect.top &&
      globalOffset.dy <= containerRect.bottom) {
    nearestY = globalOffset.dy;
  } else {
    if ((containerRect.top - globalOffset.dy).abs() >
        (containerRect.bottom - globalOffset.dy).abs()) {
      nearestY = containerRect.bottom;
    } else {
      nearestY = containerRect.top;
    }
  }

  // X coordinate
  double nearestX = 0;
  if (globalOffset.dx >= containerRect.left &&
      globalOffset.dx <= containerRect.right) {
    nearestX = globalOffset.dx;
  } else {
    if ((containerRect.left - globalOffset.dx).abs() >
        (containerRect.right - globalOffset.dx).abs()) {
      nearestX = containerRect.right;
    } else {
      nearestX = containerRect.left;
    }
  }
  print(
      "Global[${globalOffset.dx}, ${globalOffset.dy}], Found=[$nearestX, $nearestY]");

  return Offset(nearestX, nearestY);
}

On your GestureDetector, use it like this :

final GestureDetector paintGesture = GestureDetector(
  onPanUpdate: (DragUpdateDetails details) {
    setState(() {
      RenderBox renderBox = context.findRenderObject();
      // Use the globalToLocal method if you want the local coordinates, not localToGlobal
      Offset _localPosition = renderBox
                      .globalToLocal(_offsetInBox(details.globalPosition));
      _points = List.from(_points)..add(_localPosition);
    });
  },
  onPanEnd: (DragEndDetails details) {
      _points.add(null);
  },
  child: sketchArea,
);

final Container sketchArea = Container(
  key: containerKey,
  color: Colors.white,
  child: CustomPaint(
    painter: Signature(points: _points),
    size: Size.infinite,
  ),
);
leb1755
  • 1,386
  • 2
  • 14
  • 29