flutter中Listener与GestureDetector的区别

flutter中有两种触摸事件监听方式,一个是Listener,一个是GestureDetector。

这两个有什么区别呢? 换句话说,什么情况下使用Listener,什么情况使用GestureDetector呢?

  • 区别之一

    先看两者的使用时的参数。

  GestureDetector({
    Key? key,
    this.child,
    this.onTapDown,
    this.onTapUp,
    this.onTap,
    this.onTapCancel,
    this.onSecondaryTap,
    this.onSecondaryTapDown,
    this.onSecondaryTapUp,
    this.onSecondaryTapCancel,
    this.onTertiaryTapDown,
    this.onTertiaryTapUp,
    this.onTertiaryTapCancel,
    this.onDoubleTapDown,
    this.onDoubleTap,
    this.onDoubleTapCancel,
    this.onLongPressDown,
    this.onLongPressCancel,
    this.onLongPress,
    this.onLongPressStart,
    this.onLongPressMoveUpdate,
    this.onLongPressUp,
    this.onLongPressEnd,
    this.onSecondaryLongPressDown,
    this.onSecondaryLongPressCancel,
    this.onSecondaryLongPress,
    this.onSecondaryLongPressStart,
    this.onSecondaryLongPressMoveUpdate,
    this.onSecondaryLongPressUp,
    this.onSecondaryLongPressEnd,
    this.onTertiaryLongPressDown,
    this.onTertiaryLongPressCancel,
    this.onTertiaryLongPress,
    this.onTertiaryLongPressStart,
    this.onTertiaryLongPressMoveUpdate,
    this.onTertiaryLongPressUp,
    this.onTertiaryLongPressEnd,
    this.onVerticalDragDown,
    this.onVerticalDragStart,
    this.onVerticalDragUpdate,
    this.onVerticalDragEnd,
    this.onVerticalDragCancel,
    this.onHorizontalDragDown,
    this.onHorizontalDragStart,
    this.onHorizontalDragUpdate,
    this.onHorizontalDragEnd,
    this.onHorizontalDragCancel,
    this.onForcePressStart,
    this.onForcePressPeak,
    this.onForcePressUpdate,
    this.onForcePressEnd,
    this.onPanDown,
    this.onPanStart,
    this.onPanUpdate,
    this.onPanEnd,
    this.onPanCancel,
    this.onScaleStart,
    this.onScaleUpdate,
    this.onScaleEnd,
    this.behavior,
    this.excludeFromSemantics = false,
    this.dragStartBehavior = DragStartBehavior.start,
  }) 
Listener({
    Key? key,
    this.onPointerDown,
    this.onPointerMove,
    this.onPointerUp,
    this.onPointerHover,
    this.onPointerCancel,
    this.onPointerSignal,
    this.behavior = HitTestBehavior.deferToChild,
    Widget? child,
  })

可以看出Listener中监听的都是最原始的触摸事件

而GestureDetector可以识别各种各样的触摸手势,但其内部也是基于Listener来实现的。


这样看来大部情况下,使用GestureDetector足够了,而且也非常方便。使用Listener的话,很多手势还需要自己根据最原始的触摸事件来判断,比较麻烦。

  • 区别二

GestureDetector 有竞争机制,Listener没有。

也就是说,当子widget与父widget需要处理相同的触摸事件时,GestureDetector可以通过竞争机制来解决事件冲突,而Listener不会处理这种冲突。


来看下面的例子。

  1. 都使用GestureDetector的情况
Widget test1WidgetBuild(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("点击事件测试"),
      ),
      body: Center(
        child: GestureDetector(
          onTap: () {
            print("红色区域点击");
          },
          child: Container(
            width: 200,
            height: 200,
            color: Colors.red,
            child: Center(
              child: GestureDetector(
                onTap: () {
                  print("蓝色区域点击");
                },
                child: Container(
                  width: 100,
                  height: 100,
                  color: Colors.blue,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }


  • 点击蓝色区域打印:
蓝色区域点击
  • 点击红色区域打印:
红色区域点击
  1. 都使用Listener的情况
Widget test2WidgetBuild(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("点击事件测试"),
      ),
      body: Center(
        child: Listener(
          onPointerUp: (PointerUpEvent event) {
            print("红色区域点击");
          },
          child: Container(
            width: 200,
            height: 200,
            color: Colors.red,
            child: Center(
              child: Listener(
                onPointerUp: (PointerUpEvent event) {
                  print("蓝色区域点击");
                },
                child: Container(
                  width: 100,
                  height: 100,
                  color: Colors.blue,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  • 点击蓝色区域打印:
蓝色区域点击
红色区域点击
  • 点击红色区域打印:
红色区域点击
  1. 父Widget使用Listener 子Widget使用GestureDetector
Widget test3WidgetBuild(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("点击事件测试"),
      ),
      body: Center(
        child: Listener(
          onPointerUp: (PointerUpEvent event) {
            print("红色区域点击");
          },
          child: Container(
            width: 200,
            height: 200,
            color: Colors.red,
            child: Center(
              child: GestureDetector(
                onTap: () {
                  print("蓝色区域点击");
                },
                child: Container(
                  width: 100,
                  height: 100,
                  color: Colors.blue,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  • 点击蓝色区域打印:
红色区域点击
蓝色区域点击

至于就里为什么是先打印红色点击后打印蓝色点击?, 后面再仔细研究研究下


  • 点击红色区域打印:
红色区域点击
  1. 父Widget使用GestureDetector 子Widget使用Listener
 Widget test4WidgetBuild(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("点击事件测试"),
      ),
      body: Center(
        child: GestureDetector(
          onTap: () {
            print("红色区域点击");
          },
          child: Container(
            width: 200,
            height: 200,
            color: Colors.red,
            child: Center(
              child: Listener(
                onPointerUp: (PointerUpEvent) {
                  print("蓝色区域点击");
                },
                child: Container(
                  width: 100,
                  height: 100,
                  color: Colors.blue,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  • 点击蓝色区域打印:
蓝色区域点击
红色区域点击
  • 点击红色区域打印:
红色区域点击




版权声明:本文为凸然网站的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:flutter中Listener与GestureDetector的区别

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐