在 Flutter 中转换手势检测器(带堆栈)

Posted

技术标签:

【中文标题】在 Flutter 中转换手势检测器(带堆栈)【英文标题】:Transform Gesture Detector in Flutter(with Stack) 【发布时间】:2018-11-05 13:33:03 【问题描述】:

在我的代码中,我使用手势检测器在用户拖动时拉出我的菜单。但是当我拉起菜单时,GestureDetector 的 hitbox 没有改变,所以当我想把它放回去时,它只记录拖动初始的 hitbox,而不是新的 hitbox(我将小部件转换到的位置)

希望你能明白这一点^^

代码如下:

Stack(children: [
  Column(
    children: <Widget>[
      Expanded(
          child: TabBarView(children: <Widget>[
        CostumCard(
          imgUrl: url,
        ),
        CostumCard(
          imgUrl: url,
        ),
      ]))
    ],
  ),
  IgnorePointer(
    child: Opacity(
      opacity: opacity,
      child: Container(color: Colors.black),
    ),
  ),
  Transform(
    transformHitTests: true,
    transform: Matrix4.translationValues(
        0.0, MediaQuery.of(context).size.height - 80 - 70, 0.0),
    child: Transform(
      transformHitTests: true,
      transform: Matrix4.translationValues(0.0, yTransform, 0.0),
      child: GestureDetector(
        onVerticalDragStart: (DragStartDetails details) 
          dragStartY = details.globalPosition.dy;
          dragUpdateY = dragStartY;
        ,
        onVerticalDragUpdate: (DragUpdateDetails details) 
          dragDifference =
              dragUpdateY - details.globalPosition.dy;
          yTransform -= dragDifference;
          yTransform = yTransform.clamp(-400.0, 0.0);
          setState(() 
            if (yTransform <= -400)
              yTransform = -400.0;
            else if (yTransform >= 0)
              yTransform = 0.0;
            else
              yTransform = yTransform;
            opacity = yTransform / -400 * 0.8;
            rotation = yTransform / -400 * PI;
          );
          dragUpdateY = details.globalPosition.dy;
        ,
        onVerticalDragEnd: (DragEndDetails details) 
          if (dragStartY - dragUpdateY >= 100) 
            setState(() 
              yTransform = -400.0;
              opacity = yTransform / -400 * 0.8;
              rotation = yTransform / -400 * PI;
            );
           else if (dragStartY - dragUpdateY <= 100 &&
              dragStartY - dragUpdateY >= 0) 
            setState(() 
              yTransform = 0.0;
              opacity = yTransform / -400 * 0.8;
              rotation = yTransform / -400 * PI;
            );
           else if (dragStartY - dragUpdateY <= -50) 
            setState(() 
              yTransform = 0.0;
              opacity = yTransform / -400 * 0.8;
              rotation = yTransform / -400 * PI;
            );
          
        ,
        child: Container(
          width: double.infinity,
          height: 500.0,
          child: Material(
            elevation: 20.0,
            color: Colors.grey[900],
            child: Column(
              children: <Widget>[
                //menu is here
              ],
            ),
          ),
        ),
      ),
    ),
  )
]),

另外发生的情况是,当我拉起菜单时,我无法单击新菜单命中框中的任何项目,我似乎只是通过菜单单击了它下方的卡片。

【问题讨论】:

我也有类似的问题。在 GestureDetector 小部件上使用变换小部件后,小部件未检测到点击。但是使用 Positioned 小部件代替 Transform 小部件解决了一点问题。但我更喜欢使用 Transform,但我不知道如何。 github.com/flutter/flutter/issues/27587 另请参阅本文引用的其他问题。 您找到解决方案了吗? 【参考方案1】:

对此有解决方案(变通方法),但不幸的是,这是所需的行为。

我引用了一位 Flutter 维护者的话 https://github.com/flutter/flutter/issues/6606:

我们已经确定这可以正常工作。参见:#6663

然后他关闭了问题。

问题

基本上,手势检测器在变换之前不会检测到任何超出原始位置的触摸

解决办法

解决方法是使原始小部件足够大以覆盖转换。 我们可以为此添加额外的填充。例如,如果变换小部件将小部件向下移动 100 像素,只需将 100 像素的填充底部添加到原始小部件。

这将欺骗手势检测器来检测小部件内部的任何触摸和额外的填充。所以当变换移动小部件时,它会接收到触摸事件。

【讨论】:

以上是关于在 Flutter 中转换手势检测器(带堆栈)的主要内容,如果未能解决你的问题,请参考以下文章

如何检测小部件是不是在堆栈中重叠?

Flutter/Dart Uri 没有在 URL 中转义冒号“:”

Flutter 如何将裁剪器添加到 fl_chart (CustomPainter)

视图已绘制但未检测到手势识别器

Dart/Flutter 不使用 Inkwell 和手势检测器更改页面

FL studio12怎么制作3d环绕音(求教程)