【问题标题】:Flutter: how to prevent touch events being passed down to children?Flutter:如何防止触摸事件传递给孩子?
【发布时间】:2021-10-18 06:29:13
【问题描述】:

我正在尝试将我的整个应用程序包装在一个小部件中,以防止触摸事件根据某些条件通过视图层次结构向下传递。我已经有一个WrapperlifecycleListener

@override
  Widget build(BuildContext context) {
    return WrapperAppLifecycleListener(
      child: Listener(
        onPointerDown: (_) {
          //other stuff I do
        },
        child: MyApp(),
      ),
    );
  }

我期待能够做这样的事情:

 onPointerDown: (_) {
          if(passThrough){
              return true;
          } else {
              return false;
          }
        },

但到目前为止我发现的所有小部件都将void 作为其回调的返回类型,是否有任何小部件可以做类似的事情?

编辑:当用户与应用程序本身交互时,条件会发生变化,因此 IgnorePointer 或 AbsorbPointer 在这种情况下将不起作用。为了更清楚地考虑我想在触摸输入后禁用所有触摸输入的情况,因此假设:

@override
  Widget build(BuildContext context) {
    return WrapperAppLifecycleListener(
      child: Listener(
        
        onPointerDown: (_) {
          
              if(absorb){
                  return false;
              } else {
                  return true;
              }
          absorb = true;
          Future.delayed(Duration(seconds:2)).then((value) => absorb = false);
        },
        child: MyApp(),
      ),
    );
  }

【问题讨论】:

  • “触摸事件”是指基本上所有的输入事件?
  • 我建议使用IgnorePointer() 之类的东西。它有一个ignore 字段,可以设置为真或假,这将避免其任何子节点接收命中事件。
  • @nvoigt 好吧,重点是单击,但我可以处理任何事件
  • @SupremeDeity 我对此进行了调查,问题是我还需要知道何时在该级别发生点击,并且 IgnorePointer 似乎没有提供,除非我错过了一些东西。抱歉,如果不清楚,我会更新我的问题
  • 以上仅适用于您需要检测每个级别的事件时,如果您只需要检测父级别的点击事件,仍然推荐AbsorbPointer()

标签: flutter


【解决方案1】:

您的树中似乎需要 AbsorbPointer (link) 或 IgnorePointer (link) 小部件。两者都可以通过布尔属性进行控制。

有关差异的解释,请参阅Flutter AbsorbPointer vs IgnorePointer difference

【讨论】:

    【解决方案2】:

    我在寻找更好的解决方案时最终做的是:

    class GestureInterceptor extends StatefulWidget {
      final Widget child;
    
      const GestureInterceptor({required this.child});
    
      @override
      _GestureInterceptorState createState() => _GestureInterceptorState();
    }
    
    class _GestureInterceptorState extends State<GestureInterceptor> {
      var absorbTaps = false;
    
      @override
      Widget build(BuildContext context) {
        return AbsorbPointer(
          absorbing: absorbTaps,
          child: WrapperAppLifecycleListener(
            child: Listener(
              onPointerDown: (_) {
               
                setState(() {
                  absorbTaps = true;
                });
                Future.delayed(Duration(milliseconds: 400))
                    .then((value) => setState(() {
                          absorbTaps = false;
                        }));
              },
              child: widget.child,
            ),
          ),
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-04
      • 1970-01-01
      • 1970-01-01
      • 2019-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多