Flutter:忽略 Widget 上的触摸事件

97

我想在其他小部件的顶部放置一张模糊的图片,但是这样做时,我无法与其下方的小部件进行交互。


可能是Flutter中如何实现“磨砂玻璃”效果?的重复问题。 - creativecreatorormaybenot
并不是真的@creativecreatorormaybenot,我想让上一页看起来模糊,而不是放置一张随机图片和内容,一个框清晰可见,就像悬停在它上面,并带有一个投影。 - Mohamed Mohamed
是的,我明白了。但是因为Flutter仅与“Widget”一起使用,所以那个问题的答案也适用于您的问题。您整个页面可以简单地用“BackdropFilter”包装起来。 - creativecreatorormaybenot
我已经尝试过了,黑色仍然显示。我不知道那个黑色是从哪里来的。嗯,我有点知道,只有在导航到函数之后才会发生。除非还有另一种方法可以淡入一个小部件、传递数据,如果有任何数据发生了变化,也可以返回它? - Mohamed Mohamed
3个回答

202

解决方法

您可以通过将BackdropFilter包裹在IgnorePointer中来解决交互问题(即无法与模糊图像下方的Widget进行交互)。

这意味着IgnorePointer是这里的解决方法,因为它将忽略所有传递给它的Widget子元素的触摸事件。

IgnorePointer(child: BackdropFilter(...),)

您可以通过更改ignoringbool值来调整此属性:

IgnorePointer(ignoring: false, ...)

这将再次启用所有触摸事件

吸收

有趣的是,这里有一些有趣的信息,但与问题无关。您可以使用AbsorbPointerWidget,将发生在其子代上的所有触摸事件 反射到 它自己身上。


当它可见时怎么样?当我能看到它时,我可以与它交互吗?唯一不想被访问的时候是它被隐藏的时候。 - Mohamed Mohamed
从Flutter 3开始不再起作用。 - Dennis Barzanoff
@DenisBarzanov 你具体遇到了什么问题?IgnorePointerAbsorbPointer小部件没有被更改。 - creativecreatorormaybenot
这只是在我的特定情况下出现的问题。原来从Flutter 3开始,他们将gestureSettings设置为必需的,这破坏了我的自定义RenderWidget - Dennis Barzanoff
有类似于AbsorbDrag Widget的东西吗? - emrich
显示剩余2条评论

74
你可以使用IgnorePointerAbsorbPointer
  • IgnorePointer

    IgnorePointer(
      child: ElevatedButton(
        onPressed: () {},
        child: Text('Not clickable Button'),
      ),
    );
    
  • AbsorbPointer

    AbsorbPointer(
      child: ElevatedButton(
        onPressed: () {},
        child: Text('Not clickable Button'),
      ),
    );
    

有什么区别?

如果您的主要小部件下面有一个小部件,它也能够接收点击事件,并且您在父小部件上使用IgnorePointer,则子小部件仍将接收点击事件。

但是,在主小部件上使用AbsorbPointer将不允许其他小部件(位于主小部件下方)接收其点击事件。

以下是示例,展示了这两者之间的区别。

@override
Widget build(BuildContext context) {
  return SizedBox(
    width: double.infinity,
    child: Stack(
      children: <Widget>[
        Positioned(
          left: 0,
          width: 250,
          child: ElevatedButton(
            color: Colors.red,
            onPressed: () => print("Button 1"),
            child: Text("Button 1"),
          ),
        ),
        Positioned(
          right: 0,
          width: 250,
          child: IgnorePointer( // replace this with AbsorbPointer and button 1 won't receive click
            child: ElevatedButton(
              onPressed: () => print("Button 2"),
              child: Text("Button 2"),
            ),
          ),
        ),
      ],
    ),
  );
}

这难道不会同时阻止按钮2的onclick事件吗?当我在新创建的应用程序中运行上述代码时,我没有看到打印按钮2的输出。 - Boiler Bill
那么 ignorePointer() 小部件怎么办呢?我们该如何处理? - Flutter

0

更新

其他答案非常吸引人。

让我们看一个使用IgnorePointer小部件的实际示例。

当我们开始尝试实现像切换小部件上的选择以删除或类似于此类东西时,这种情况非常普遍。

示例场景:长按WhatsApp消息并在顶部显示删除选项。如果在此选项处于活动状态时点击其他任何地方,它将消失。

我是这样实现的。

appBar: AppBar(
         title: Text('MyApp'), 
         actions: [
            if (_selected != null) // <-- Delete button only appear something selected.
               IconButton(
               icon: Icon(Icons.delete),
               onPressed: () { 
                   // Delete Code here
               }
         ]
      ),
body: GestureDetector(
           behavior: HitTestBehavior.opaque,
           onTap: () { 
                 print('Tapped');
                 setState(() { _selected = null });
           },
           child: IgnorePointer(
           ignoring: _selected != null ? true : false, // <-- Ignore only when selecting something.
           child: Column(
             children: [
              ...

              // This is a sample message 

              GestureDetector(
              onLongPress: () {  
                 setState(() { _selected = messageId  });
              }
              child: Container(
                 child: Text('This is a message'),
              ),
               
              ...

结果:

希望能对某些人有所帮助!祝你有美好的一天。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接