【问题标题】:flutter : Get Local position of Gesture Detectorflutter :获取手势检测器的本地位置
【发布时间】:2018-08-24 08:12:24
【问题描述】:

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

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 小部件之外。为了获得本地职位,我有什么遗漏的吗?

【问题讨论】:

  • 如果您包含实际检查本地和全局位置的代码,将会很有帮助。但是我可能仍然可以告诉你发生了什么。

标签: dart flutter


【解决方案1】:

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

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 恰好在屏幕的左上角,则结果将匹配全局坐标。

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

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

【讨论】:

  • 当我打印全局位置和本地位置的偏移量时,我对它们都有相同的值。我写了相同的值,因为在事件泛更新中我确实将全局转换为本地事物。它仍然具有相同的价值。
  • 您是否将手势检测器封装在 Builder 中或为其创建新的无状态小部件?因为根据我的解释,否则这是预期的行为。
  • 如果您确实更改了某些内容但仍然遇到同样的问题,请使用新代码更新您的问题
  • 非常感谢!
【解决方案2】:

感谢@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 类中。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      您可以使用 DragUpdateDetails.localPosition 获取 GestureDetector 的本地位置

      GestureDetector(
        onPanUpdate: (DragUpdateDetails details) {
          print('onPanUpdate');
          print(details.localPosition);
        },
      )
      

      【讨论】:

        猜你喜欢
        • 2022-01-26
        • 2019-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-06
        • 2019-03-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多