美文网首页
Flutter踩坑系列:滑动手势监听不到

Flutter踩坑系列:滑动手势监听不到

作者: Blutter | 来源:发表于2020-02-14 19:55 被阅读0次

    作者:Dreamy

    问题描述

    在PageView外部使用GestureDetector监听不到左滑手势。
    如下代码,水平滑动的PageView只监听到了垂直方向的拖拽手势,却监听不到水平方向的拖拽手势。

    GestureDetector(
      onVerticalDragStart: (details) => print('onVerticalDragStart'),
      onVerticalDragEnd: (details) => print('onVerticalDragEnd'),
      onHorizontalDragStart: (details) => print('onHorizontalDragStart'),
      onHorizontalDragEnd: (details) => print('onHorizontalDragEnd'),
      child: PageView(
        children: [
          Container(color: Colors.amber),
          Container(color: Colors.blue),
          Container(color: Colors.deepOrangeAccent),
        ],
      ),
    );
    
    日志

    原因分析

    水平手势已经被横向滑动的PageView监听,所以通过GestureDetector是无法再次监听的,只能使用Listener对原始指针进行监听,进而达到监听横向滑动的效果。下文具体介绍Flutter的手势监听机制。

    Pointer

    Pointer Event指针事件是指最原始的触摸事件,一次事件包括触摸到屏幕、在屏幕上移动到离开屏幕。 使用Listener组件来监听指针事件,基本的回调有onPointerDown、onPointerMove、onPointerUp。

    Listener(
      child: Container(
        alignment: Alignment.center,
        color: Colors.blue,
        width: 100,
        height: 100,
      ),
      onPointerDown: (event) => print('onPointerDown'),
      onPointerMove: (event) => print('onPointerMove'),
      onPointerUp: (event) => print('onPointerUp'),
    ),
    
    

    Listener的behavior参数

    // How to behave during hit tests.
    enum HitTestBehavior {
      // Targets that defer to their children receive events within their bounds
      // only if one of their children is hit by the hit test.
      deferToChild,
    
      // Opaque targets can be hit by hit tests, causing them to both receive
      // events within their bounds and prevent targets visually behind them from
      // also receiving events.
      opaque,
    
      // Translucent targets both receive events within their bounds and permit
      // targets visually behind them to also receive events.
      translucent,
    }
    
    

    首先要了解两个概念 一个是渲染层级,还有一个是Widget的树结构。当手指点击之后会先通过渲染层级和behavior参数确定HitTest命中的组件,然后根据树结构依次向上传递Pointer Event。透明Widget一般HitTest都会失败,但是behavior参数可以依照如下说明进行设定。
    deferToChild:当子节点widget的HitTest命中测试成功时,该节点一定会响应。
    opaque:将当前节点Widget当作是不透明的进行处理(就算是透明的组件)。
    translucent:透传,正常情况下HitTest只会响应渲染层级上面的组件。
    IgnorePointer组件 被IgnorePointer组件包裹的子树及其本身都不会处理PointerEvent事件。
    AbsorbPointer组件 被AbsorbPointer组件包裹的子树不会处理PointerEvent事件,但是AbsorbPointer组件本身会处理。

    GestureDetector组件

    GestureDetector组件对基本的PointerEvent事件进行了语义封装,通过GestureRecognizer使用Listener将PointerEvent转义成onTap、onDoubleTap、onLongPress、onPanDown、onVeticalDragUpdate等等接口。
    Arena: Flutter定义了一个Arena手势竞技场,对有冲突的手势进行判断最后选出唯一的一个获胜者并处理事件。例如水平和垂直的ListView会根据横竖的滑动分量进行判断。
    Tip: 手势冲突只是手势级别的,而手势是对原始指针的语义化的识别,所以在遇到复杂的冲突场景时,都可以通过Listener直接识别原始指针事件来解决冲突。

    Notification

    NotificationListener组件可以用来监听从子结构传递过来的通知,和手势通知不同,这种Notification可以选择是否还要往上传递。 常用的是ScrollStartNotification、ScrollUpdateNotification等滑动通知,也可以自定义通知dispatch向上分发。

    相关文章

      网友评论

          本文标题:Flutter踩坑系列:滑动手势监听不到

          本文链接:https://www.haomeiwen.com/subject/sgujfhtx.html