Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flutter : Get Local position of Gesture Detector

Tags:

flutter

dart

I have problems to get real local position on gesture detector widget using pan update.

new Center(    
  child new Container(
       height: 150.0,
       width: 150.0,
       decoration: new BoxDecoration(
         borderRadius: new BorderRadius.circular(5.0),
         color: Colors.white,
      ),
      child: new GestureDetector(
      onPanUpdate: (details) => onPanUpdate(context, details),
      child: new CustomPaint(
         painter: new MyPainter(
             points: points,
             limitBottom:height - 125.0,
             limitTop: 10.0,
             limitLeft: 5.0,
             limitRight: width - 55.0
         ),
       ),
    ),
  ),  
)

when I print the the Offset of global position && local position, I've got same value for both of them. in Result it was painted outside of my Container widget. Is there anything I missed to get local position?

like image 867
M. Plant Avatar asked Aug 24 '18 08:08

M. Plant


People also ask

What is gesturedetector in flutter?

GestureDetector In Flutter. When it comes to creating applications… | by Raksha Goswami | FlutterDevs W hen it comes to creating applications, you have to handle user reactions such as touch and drags. This makes your application interactional beneficially handle gestures, you need to listen to the gestures and greet them.

How to detect what kind of gesture is happening on widget?

If you need to detect what kind of gesture is happening on a widget, the easiest way is by wrapping the widget as the child of GestureDetector. It's a StatelessWidget that can have a lot of callback functions each for different types of gestures.

How to get the offset of a gesturedetector?

By using the context for your gesture detector, you'd instead be measuring the distance between 2 and 3, which will give you the offset you want. There's two ways to fix this - either you can wrap your GestureDetector in a Builderwidget, or you can create a new Stateful/Stateless widget that encapsulates just the GestureDetector.

What is the use of gesture detector?

Gesture Detector is used to detect user’s gesture such as tap, double tap, drag, flick, pinch, zoom, panning etc. Gesture Detector is useful for any mobile app user to interact with mobile applications. Gesture Detector is a stateless widget which is used for different touch events.


2 Answers

I assume you're using something like this to get the local position:

RenderBox getBox = context.findRenderObject();
var local = getBox.globalToLocal(start.globalPosition);

The reason you'd be getting the wrong offset after doing that has to do with the context you're using to find the local position.

If you're using the overall widget's context, essentially what you're doing is calculating the offset within the overall widget. i.e.

YourWidget <-- context
  Center
   Container
     GestureDetector
     ...

Let's say that the screen looks something like this:

1__________________________   
|                          |  <--- YourWidget
|       2_________         |
|       | gesture |        |
|       | detector|        |
|       |   3.    |        |
|       |_________|        |
|                          |
|__________________________|

With 1 being the top left of your overall widget (and the screen), 2 being the top left of your gesture detector, and 3 being the point where you tap.

By using the context of YourWidget, you're calculating the position of the tap based on the difference between 1 and 3. If 1 happens to be at the top left of the screen, the result will match the global coordinates.

By using the context for your gesture detector, you'd instead be measuring the distance between 2 and 3, which will give you the offset you want.

There's two ways to fix this - either you can wrap your GestureDetector in a Builder widget, or you can create a new Stateful/Stateless widget that encapsulates just the GestureDetector. I'd personally recommend creating a new widget.

like image 83
rmtmckenzie Avatar answered Oct 08 '22 01:10

rmtmckenzie


Wrapping it with a StatelessWidget works fine for me, thanks to @rmtmckenzie

Here my code:

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(),
      body: _Foo(),
    );
  }
}

class _Foo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onLongPressDragStart: (details) => _onLongPressDragStart(details, context),
      onLongPressDragUpdate: (details) => _onLongPressDragUpdate(details, context),
      onLongPressDragUp: (details) => _onLongPressDragUp(details, context),
      child: FlareActor(
        "assets/test.flr",
        alignment: Alignment.center,
        fit: BoxFit.contain,
      ),
    );
  }

  void _onLongPressDragStart(GestureLongPressDragStartDetails details, BuildContext context) {
    print('_onLongPressDragStart details: ${details.globalPosition}');
  }

  void _onLongPressDragUpdate(GestureLongPressDragUpdateDetails details, BuildContext context) {
    var localTouchPosition = (context.findRenderObject() as RenderBox).globalToLocal(details.globalPosition);
    print('_onLongPressDragUpdate details: ${details.globalPosition} - localTouchPosition: $localTouchPosition');
  }

  void _onLongPressDragUp(GestureLongPressDragUpDetails details, BuildContext context) {
    print('_onLongPressDragUp details: ${details.globalPosition}');
  }
}

The important things happen in the _Foo class.

like image 29
Ralph Bergmann Avatar answered Oct 07 '22 23:10

Ralph Bergmann