如何防止在父小部件GestureDetector上触发onTapDown? [英] How do I prevent onTapDown from being triggered on a parent widgets GestureDetector?

查看:325
本文介绍了如何防止在父小部件GestureDetector上触发onTapDown?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Stack,可以在其中拖动几个小部件.此外,堆栈所在的容器还具有一个GestureDetector,可在onTapDown和onTapUp上触发该容器.我希望仅当用户在堆栈中的窗口小部件外部点击时才触发那些onTap事件.我尝试了以下代码:

I have a Stack in which several widget can be dragged around. In addition, the container that the Stack is in has a GestureDetector to trigger on onTapDown and onTapUp. I want those onTap events only to be triggered when the user taps outside of the widget in the Stack. I've tried the following code:

class Gestures extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _GesturesState();
}

class _GesturesState extends State<Gestures> {
  Color background;
  Offset pos;

  @override
  void initState() {
    super.initState();
    pos = Offset(10.0, 10.0);
  }

  @override
  Widget build(BuildContext context) => GestureDetector(
    onTapDown: (_) => setState(() => background = Colors.green),
    onTapUp: (_) => setState(() => background = Colors.grey),
    onTapCancel: () => setState(() => background = Colors.grey),
        child: Container(
          color: background,
          child: Stack(
            children: <Widget>[
              Positioned(
                top: pos.dy,
                left: pos.dx,
                child: GestureDetector(
                  behavior: HitTestBehavior.opaque,
                  onPanUpdate: _onPanUpdate,
//                  onTapDown: (_) {},  Doesn't affect the problem
                  child: Container(
                    width: 30.0,
                    height: 30.0,
                    color: Colors.red,
                  ),
                ),
              )
            ],
          ),
        ),
      );

  void _onPanUpdate(DragUpdateDetails details) {
    RenderBox renderBox = context.findRenderObject();
    setState(() {
      pos = renderBox.globalToLocal(details.globalPosition);
    });
  }
}

但是,当开始拖动窗口小部件时,也会触发最外层容器的onTap,在这种情况下,背景暂时变为绿色.设置HitTestBehavior.opaque似乎无法正常运行.也不向堆栈中的小部件添加onTapDown的处理程序.

However, when starting to drag the widget, the onTap of the outermost container is triggered as well, making the background momentarily go green in this case. Settings HitTestBehavior.opaque doesn't seem to work like I'd expect. Neither does adding a handler for onTapDown to the widget in the Stack.

那么,当用户与Stack内部的小部件进行交互时,如何防止onTapDown在最外面的GestureDetector上触发?

So, how do I prevent onTapDown from being triggered on the outermost GestureDetector when the user interacts with the widget inside of the Stack?

更新:

我遇到的问题的一个更简单的示例:

An even simpler example of the problem I'm encountering:

GestureDetector(
  onTapDown: (_) {
    print("Green");
  },
  child: Container(
    color: Colors.green,
    width: 300.0,
    height: 300.0,
    child: Center(
      child: GestureDetector(
        behavior: HitTestBehavior.opaque,
        onTapDown: (_) {
          print("Red");
        },
        child: Container(
          color: Colors.red,
          width: 50.0,
          height: 50.0,
        ),
      ),
    ),
  ),
);

点击并按住红色容器时,即使内部的GestureDetector具有HitTestBehavior.opaque,也会同时打印红色"和绿色".

When I tap and hold the red container, both "Red" and "Green" are printed even though the inner GestureDetector has HitTestBehavior.opaque.

推荐答案

正如Flutter开发人员之一所解释的:

As explained by one of the Flutter devs: https://github.com/flutter/flutter/issues/18450#issuecomment-397372078

opaque只是意味着手势检测器的整个大小都是命中区域,它不会阻止孩子被命中.要阻止对孩子的点击,请使用IgnorePointerAbsorbPointer.

opaque just means the entire size of the gesture detector is the hit region, it doesn't stop the child from being hit. To block hits on children use an IgnorePointer or AbsorbPointer.

您必须添加某种条件才能用IgnorePointer包装您的孩子Widget,这样顶部的GestureDetector将吸收水龙头.

You'll have to add some kind of condition to wrap your child Widget with IgnorePointer, that way your top GestureDetector will absorb the taps.

在您的示例中,在这些小部件之间添加IgnorePointer:

In your example, add IgnorePointer between these Widgets:

GestureDetector(
  onTapDown: (_) {
    print("Green");
  },
  child: IgnorePointer(
    child: Container(
      color: Colors.green,
      width: 300.0,
      height: 300.0,
      child: Center(
        child: GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTapDown: (_) {
            print("Red");
          },
          child: Container(
            color: Colors.red,
            width: 50.0,
            height: 50.0,
          ),
        ),
      ),
    ),
  ),
);

这篇关于如何防止在父小部件GestureDetector上触发onTapDown?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆