flutter:获取手势检测器的本地位置

时间:2018-08-24 08:12:24

标签: dart flutter

我无法使用平移更新来获取手势检测器小部件上的实际本地位置

这是我的示例代码

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
         ),
       ),
    ),
  ),  
)

当我打印全局位置和局部位置的偏移量时,它们两个的值相同。结果是它被绘制在我的Container小部件外部。有什么我想得到的本地职位吗?

4 个答案:

答案 0 :(得分:8)

我认为您正在使用类似的方法来获取本地位置:

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

这样做之后得到错误偏移的原因与您用来查找本地位置的context有关。

如果您使用的是整个窗口小部件的上下文,那么实际上,您要做的是计算整个窗口小部件内的偏移量。即

YourWidget <-- context
  Center
   Container
     GestureDetector
     ...

假设屏幕看起来像这样:

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

其中1是整个小部件(和屏幕)的左上方,2是手势检测器的左上方,3是您点击的位置。

通过使用YourWidget的上下文,您正在根据1和3之间的差值来计算抽头的位置。如果1恰好位于屏幕的左上方,则结果将与全局坐标相匹配。 / p>

通过使用手势检测器上下文,您可以测量2到3之间的距离,这将为您提供所需的偏移量。

有两种方法可以解决此问题-您可以将GestureDetector包装在Builder小部件中,或者可以创建一个仅封装GestureDetector的新的有状态/无状态小部件。我个人建议创建一个新的小部件。

答案 1 :(得分:0)

感谢@rmtmckenzie,用StatelessWidget包裹起来对我来说很好用

这是我的代码:

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}');
  }
}

重要的事情发生在_Foo类中。

答案 2 :(得分:0)

我的“点击位置”被抵消时遇到了问题。我相信这是上述相同的问题。通过阅读有关键并在此处找到小部件的位置/大小,我能够解决此类似问题:

https://medium.com/@diegoveloper/flutter-widget-size-and-position-b0a9ffed9407

因此,我不必如上所述创建另一个窗口小部件或布局生成器,但是我可以添加一个全局键,然后通过使用来自键。很酷!

  void _handleLongPress(LongPressStartDetails details) {
    final RenderBox referenceBox = _keyRink.currentContext.findRenderObject();
    var x = referenceBox.globalToLocal(details.globalPosition);
    if (x == tapPosition) {
      Vibration.vibrate(duration: 50);
      setState(() {
        _shots[_homeShotCount] = tapPosition;
      });
    }
  }

这是我的主要脚手架,您可以在其中看到添加钥匙的位置。

   return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: GestureDetector(
        key: _keyRink,
        onTapDown: _getTapPosition,
        onLongPressStart: _handleLongPress,
        child: Stack(
          children: <Widget>[
            AnimatedOpacity(
              duration: Duration(milliseconds: 2500),
              opacity: _rinkOpacity,
              child: Center(
                child: Image.asset('assets/rink.png',
                    width: size.width, height: size.height, fit: BoxFit.fill),
              ),
            ),
            Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Transform.rotate(
                    angle: animationRotate.value,
                    child: Transform.scale(
                        scale: animationDrop.value,
                        child: FlatButton(
                            onPressed: null,
                            padding: EdgeInsets.all(0.0),
                            child: Image.asset('assets/puck.png'))),
                  )
                ],
              ),
            ),
            CustomPaint(
              painter: ShapesPainter(),
              child: FractionallySizedBox(heightFactor: 1.0,widthFactor: 1.0,),
            ),
          ],
        ),
      ),
      drawer: Drawer(
        child: drawerItems,
      ),
    );
  }

答案 3 :(得分:0)

您可以使用 DragUpdateDetails.localPosition

获取 GestureDetector 的本地位置
GestureDetector(
  onPanUpdate: (DragUpdateDetails details) {
    print('onPanUpdate');
    print(details.localPosition);
  },
)