Flutter中的事件冒泡处理

打印 上一主题 下一主题

主题 1026|帖子 1026|积分 3078

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
在 Flutter 中,GestureDetector 的点击事件默认是冒泡的,即假如嵌套了多个 GestureDetector,点击事件会从最内层的 GestureDetector 开始触发,然后依次向外层传递。假如你希望控制事件的优先级或制止事件冒泡,可以使用以下方法:

1. 使用 HitTestBehavior

GestureDetector 的 behavior 属性可以控制点击事件的命中测试举动。常用的选项有:


  • HitTestBehavior.deferToChild(默认):事件会传递给子组件,假如子组件不处理,则父组件处理。
  • HitTestBehavior.opaque:事件会被当前组件捕获,不会传递给子组件。
  • HitTestBehavior.translucent:事件会同时传递给当前组件和子组件。
示例

  1. GestureDetector(
  2.   onTap: () {
  3.     // 父组件的点击事件
  4.     print('父组件点击');
  5.   },
  6.   behavior: HitTestBehavior.opaque, // 阻止事件传递给子组件
  7.   child: GestureDetector(
  8.     onTap: () {
  9.       // 子组件的点击事件
  10.       print('子组件点击');
  11.     },
  12.     child: Card(
  13.       child: Container(
  14.         width: 100,
  15.         height: 100,
  16.         color: Colors.blue,
  17.       ),
  18.     ),
  19.   ),
  20. );
复制代码
在这个例子中,由于父组件的 behavior 设置为 HitTestBehavior.opaque,点击事件会被父组件捕获,子组件的点击事件不会触发。

2. 使用 AbsorbPointer

AbsorbPointer 是一个可以制止子组件接收点击事件的组件。你可以通过设置 absorbing 属性来控制是否制止事件传递。
示例

  1. GestureDetector(
  2.   onTap: () {
  3.     // 父组件的点击事件
  4.     print('父组件点击');
  5.   },
  6.   child: AbsorbPointer(
  7.     absorbing: true, // 阻止子组件接收点击事件
  8.     child: GestureDetector(
  9.       onTap: () {
  10.         // 子组件的点击事件(不会触发)
  11.         print('子组件点击');
  12.       },
  13.       child: Card(
  14.         child: Container(
  15.           width: 100,
  16.           height: 100,
  17.           color: Colors.blue,
  18.         ),
  19.       ),
  20.     ),
  21.   ),
  22. );
复制代码
在这个例子中,由于 AbsorbPointer 的 absorbing 属性为 true,子组件的点击事件不会触发。

3. 使用 Listener

Listener 是一个更低级别的组件,可以监听原始的指针事件。你可以通过 onPointerDown 等回调来控制事件传递。
示例

  1. Listener(
  2.   onPointerDown: (event) {
  3.     // 阻止事件传递给子组件
  4.     print('父组件点击');
  5.   },
  6.   child: GestureDetector(
  7.     onTap: () {
  8.       // 子组件的点击事件(不会触发)
  9.       print('子组件点击');
  10.     },
  11.     child: Card(
  12.       child: Container(
  13.         width: 100,
  14.         height: 100,
  15.         color: Colors.blue,
  16.       ),
  17.     ),
  18.   ),
  19. );
复制代码
在这个例子中,Listener 的 onPointerDown 会捕获事件并制止其传递给子组件。

4. 你的场景的解决方案

在你的代码中,有两个嵌套的 GestureDetector,分别用于切换隐私模式和表现操作菜单。你可以通过以下方式设置优先级:
方案 1:使用 HitTestBehavior

  1. GestureDetector(
  2.   onTap: () {
  3.     // 点击切换隐私模式
  4.     Provider.of<TodoProvider>(context, listen: false).togglePrivacy(todo.id);
  5.   },
  6.   behavior: HitTestBehavior.opaque, // 阻止事件传递给子组件
  7.   child: GestureDetector(
  8.     onTap: () => _showActionMenu(context, todo),
  9.     child: Card(
  10.       child: Container(
  11.         width: 100,
  12.         height: 100,
  13.         color: Colors.blue,
  14.       ),
  15.     ),
  16.   ),
  17. );
复制代码
方案 2:使用 AbsorbPointer

  1. GestureDetector(
  2.   onTap: () {
  3.     // 点击切换隐私模式
  4.     Provider.of<TodoProvider>(context, listen: false).togglePrivacy(todo.id);
  5.   },
  6.   child: AbsorbPointer(
  7.     absorbing: true, // 阻止子组件接收点击事件
  8.     child: GestureDetector(
  9.       onTap: () => _showActionMenu(context, todo),
  10.       child: Card(
  11.         child: Container(
  12.           width: 100,
  13.           height: 100,
  14.           color: Colors.blue,
  15.         ),
  16.       ),
  17.     ),
  18.   ),
  19. );
复制代码
方案 3:使用 Listener

  1. Listener(
  2.   onPointerDown: (event) {
  3.     // 点击切换隐私模式
  4.     Provider.of<TodoProvider>(context, listen: false).togglePrivacy(todo.id);
  5.   },
  6.   child: GestureDetector(
  7.     onTap: () => _showActionMenu(context, todo),
  8.     child: Card(
  9.       child: Container(
  10.         width: 100,
  11.         height: 100,
  12.         color: Colors.blue,
  13.       ),
  14.     ),
  15.   ),
  16. );
复制代码

5. 总结



  • HitTestBehavior:通过设置 behavior 属性控制事件传递。
  • AbsorbPointer:通过 absorbing 属性制止子组件接收事件。
  • Listener:通过监听原始指针事件控制事件传递。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宝塔山

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表