Flutter 开发 GestureDetector与Listener的点击冒泡与穿透

本文比较了GestureDetector和Listener在处理子组件点击事件时的不同行为:GestureDetector阻止冒泡,只响应最内层;Listener则进行事件穿透,从上到下响应。开发者应根据需求选择合适的组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       在开发过程中,我们经常遇到父组件A有点击事件,其子组件B也有点击事件的情况,我们都知道GestureDetector和Listener都能实现对点击事件的监听,两者有什么不同的表现呢?实验如下:

1、子父节点都是GestureDetector的情况

class MyContainer extends StatelessWidget {
  const MyContainer({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          GestureDetector(
            onTap: () {
              print("parent");
            },
            child: Container(
              height: MediaQuery.of(context).size.height * 0.3,
              color: Colors.amber,
              child: GestureDetector(
                onTap: () {
                  print("child");
                },
                child: Align(
                    alignment: Alignment.center,
                    child: Container(
                      height: 80.0,
                      color: Colors.blueAccent,
                      width: MediaQuery.of(context).size.width * 0.2,
                    )),
              ),
            ),
          )
        ]);
  }
}

实际效果是:点击蓝色部分只打印“child”,点击黄色部分打印“parent”。

结论:GestureDetector会阻止冒泡,只执行最里面一层。

2、父节点为GestureDetector,子节点为Listener

class MyContainer extends StatelessWidget {
  const MyContainer({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          GestureDetector(
            onTap: () {
              print("parent");
            },
            child: Container(
              height: MediaQuery.of(context).size.height * 0.3,
              color: Colors.amber,
              child: Listener(
                onPointerDown: (e) {
                  print("child");
                },
                child: Align(
                    alignment: Alignment.center,
                    child: Container(
                      height: 80.0,
                      color: Colors.blueAccent,
                      width: MediaQuery.of(context).size.width * 0.2,
                    )),
              ),
            ),
          )
        ]);
  }
}

实际效果是:点击蓝色部分先打印“child”再打印“parent”,点击黄色部分打印“parent”。

结论:Listener会进行事件穿透,多层响应

3、父节点为Listener,子节点为GestureDetector

class MyContainer extends StatelessWidget {
  const MyContainer({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Listener(
            onPointerDown: (e) {
              print("parent");
            },
            child: Container(
              height: MediaQuery.of(context).size.height * 0.3,
              color: Colors.amber,
              child: GestureDetector(
                onTap: () {
                  print("child");
                },
                child: Align(
                    alignment: Alignment.center,
                    child: Container(
                      height: 80.0,
                      color: Colors.blueAccent,
                      width: MediaQuery.of(context).size.width * 0.2,
                    )),
              ),
            ),
          )
        ]);
  }
}

实际效果是:点击蓝色部分先打印“parent”再打印“child”,点击黄色部分打印“parent”。

结论:Listener会进行事件穿透,多层响应,由上往下

 4、子父节点都是Listener

class MyContainer extends StatelessWidget {
  const MyContainer({super.key});

  @override
  Widget build(BuildContext context) {
    return Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Listener(
            onPointerDown: (e) {
              print("parent");
            },
            child: Container(
              height: MediaQuery.of(context).size.height * 0.3,
              color: Colors.amber,
              child: Listener(
                onPointerDown: (e) {
                  print("child");
                },
                child: Align(
                    alignment: Alignment.center,
                    child: Container(
                      height: 80.0,
                      color: Colors.blueAccent,
                      width: MediaQuery.of(context).size.width * 0.2,
                    )),
              ),
            ),
          )
        ]);
  }
}

实际效果是:点击蓝色部分先打印“child”再打印“parent”,点击黄色部分打印“parent”。

结论:Listener会进行事件穿透,多层响应

总结:

        GestureDetector会阻止事件的冒泡传递,只执行最里面一层;Listener会进行事件穿透,多层响应,并从上往下进行响应。实际项目中要根据需要适合搭配使用~

Keychron Q2是一款机械键盘,以其出色的性能和便携设计受到许多用户的喜爱。以下是关于这款键盘的一些基本使用说明: ### 一、初次设置 1. **包装内容**:打开包装盒后,您会发现除了键盘本身之外,通常还包含USB Type-C连接线以及拔键器等配件。 2. **电源开关位置**:右上角有一个物理拨动式的电源按钮,默认处于关闭状态,在首次开机前需要手动开启。 ### 二、蓝牙配对指南(如果支持) - 打开设备蓝牙功能; - 将键盘切换到“BT”模式,并长按FN+ESC进入蓝牙配对界面; - 根据屏幕提示完成其他无线装置之间的匹配过程; ### 三、有线/2.4G连接步骤 对于更稳定高效的输入体验,推荐采用Type C数据线直插电脑主机的方式或通过随机附赠的接收器建立低延迟的2.4GHz频段通信链路。只需将对应的端口对接即可快速激活并正常工作。 ### 四、自定义宏命令及灯效调整 借助官方驱动程序,用户能够轻松编辑每个按键对应的动作序列或是调节RGB背光色彩组合方案来满足个性化需求。此外还可以保存多套配置文件以便随时切换适应不同应用场景下的操作习惯。 ### 五、清洁保养建议 定期清理缝隙间的灰尘杂物可以延长使用寿命。当遇到污渍时请先断电再利用干净柔软布料轻轻擦拭表面区域。 以上就是针对keychron q2的主要介绍啦!希望能帮到你哦~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值