Flutter 触摸事件监听 Listener 、手势识别示例

妖精的绣舞 提交于 2020-07-27 04:17:47

文章目录
触摸监听 Listener
示例
手势识别 GestureDetector
点击、双击、长按、水平滑动、垂直滑动
跟随手指移动效果
缩放效果
手势识别基类 GestureRecognizer
使用实例
自定义手势识别
在Android开发中,完整的触摸事件会经历:手指按下(ACTION_DOWN)、手指移动(ACTION_MOVE)、和手指抬起(ACTION_UP),三个阶段,在Flutter中提供Listener组件来实现类似的功能。Android还提供了GestureDetector来帮助我们识别一些基本的触摸手势,如类似于:单击、双击、长按等操作,在Flutter中也提供了手势识别组件GestureDetector来实现类似的功能。









触摸监听 Listener
响应常见指针事件而调用回调的 widget。

查看构造函数支持的属性:

const Listener({
    Key key,
    this.onPointerDown,// 按下手指回调
    this.onPointerMove,// 移动手指回调
    this.onPointerUp,// 抬起手指回调
    this.onPointerCancel,// 取消回调
    this.onPointerSignal,// 该对象在触摸发生时回调
    this.behavior = HitTestBehavior.deferToChild,// 命中测试期间的行为方式
    Widget child,// 子布局
  })

示例
居中显示的一个区域,触摸区域输出对应的坐标












示例伪代码如下:

Listener(
  child: Container(
    alignment: Alignment.center,
    color: Colors.blue,
    width: 300.0,
    height: 300.0,
  ),
  onPointerDown: (PointerDownEvent event){
    print("onPointerDown:${event.position.toString()}");
  },
  onPointerMove: (PointerMoveEvent event){
    print("onPointerMove:${event.position.toString()}");
  },
  onPointerUp: (PointerUpEvent event){
    print("onPointerUp:${event.position.toString()}");
  },
  onPointerSignal: (PointerSignalEvent event){
    print("onPointerSignal:${event.position.toString()}");
  },
  onPointerCancel: (PointerCancelEvent event){
    print("onPointerCancel:${event.position.toString()}");
  },
),

当触发指针事件时,参数PointerDownEvent、PointerMoveEvent、PointerUpEvent中的event会记录下触摸相关的信息。























这些信息来自PointerEvent,查看其构造函数中字段信息:

const PointerEvent({
    this.timeStamp = Duration.zero, // 事件调度的时间
    this.pointer = 0, // 指针的唯一标识符,不能重用
    this.kind = PointerDeviceKind.touch, //为其生成事件的输入设备的类型:touch(触摸设备),mouse(鼠标),stylus(手写笔),invertedStylus(手写笔),unknown(未知设备)
    this.device = 0, // 指示设备的唯一标识符,可在各种交互中重复使用
    this.position = Offset.zero, // 指针位置的坐标
    Offset localPosition, // 指针位置的本地坐标
    this.delta = Offset.zero, // 自上一个 PointerMoveEvent 或 PointerHoverEvent 后,指针移动的逻辑像素距离。
    Offset localDelta, // 事件接收者的本地坐标
    this.buttons = 0, // 使用 Button 常量的位字段
    this.down = false, // 设置指针当前是否向下。
    this.obscured = false, 
    this.pressure = 1.0, // 按压力度
    this.pressureMin = 1.0, // 按压力度最小值,该数字始终小于或等于1.0。
    this.pressureMax = 1.0, // 按压力度最大值,它将始终大于或等于1.0。
    this.distance = 0.0, // 被检测物体与输入表面的距离
    this.distanceMax = 0.0, // 如果此输入设备无法检测到“悬停触摸”输入事件,则为0.0。
    this.size = 0.0, // 屏幕被按下的区域。
    this.radiusMajor = 0.0, // 沿椭圆的接触椭圆的半径
    this.radiusMinor = 0.0, // 沿椭圆的接触椭圆的半径
    this.radiusMin = 0.0, // 可以为此指针报告 radiusMajor 和 radiusMinor 的最小值
    this.radiusMax = 0.0, // 可以为此指针报告 radiusMajor 和 radiusMinor 的最大值
    this.orientation = 0.0, // 指针移动方向,是一个角度值
    this.tilt = 0.0, // 被检测物体的倾斜角度
    this.platformData = 0, // 与事件关联的特定于平台的不透明数据。
    this.synthesized = false, // 设置事件是否由Flutter合成。
    this.transform, // 用于将该事件从全局坐标转换为事件接收者的坐标空间的转换。
    this.original, // 应用任何 transform 之前的原始未转换的 PointerEvent 
  }) 

需要注意的是:





























onScale,onVerticalDrag,onHorizontalDrag 三个参数不能同时使用,
onScale ,onPan不能同时使用
onPan,onVerticalDrag,onHorizontalDrag 三个参数不能同时使用
否则会提示:Incorrect GestureDetector arguments. 参数冲突。


示例效果:


点击、双击、长按、水平滑动、垂直滑动
在蓝色区域内点击、双击、长按、水平滑动、垂直滑动在控制台可以看到回调信息输出。

跟随手指移动效果

实现思路就是在onPan回调里面处理widget的位置。


缩放效果

实现思路就是在onScale回调里面处理widget的宽高。


手势识别基类 GestureRecognizer
所有手势识别器都继承的基类。查看GestureDetector源码发现,GestureDetector的相关手势识别也是继承自该类。

例如双击回调监听使用到了DoubleTapGestureRecognizer:


在之前的文章 Flutter 文本 Text 参数图文理解 中使用了TextSpan来拼接文本,并在特定的文本区域实现点击事件。

由于GestureDetector包裹的child必须是widget,而TextSpan并不是widget所以这里不能使用GestureDetector,但是TextSpan中提供了更为继承的手势识别类GestureRecognizer,通过该类我们可以实现手势监听。

使用实例

伪代码实现如下:


自定义手势识别
当有多个手势时,可能会产生冲突。如对图片进行点击、长按、缩放等操作的时候,如何识别用户当前是点击还是长按,缩放。如果想要精确地处理复杂交互手势,可自定义手势识别器来处理冲突问题。

如下示例:分别给红蓝背景的框框设置点击事件,但是点击蓝色背景时,底部的红色框框没有点击事件没有被识别。

上面的示例中想要红色框框也能识别手势事件,该怎么实现呢?

上面我们也介绍了指针的基本事件Listener,将第一个GestureDetector改为Listener组件,再来看一下效果:

可以看到使用Listener组件能够优先识别到触摸事件。但是想实现最外层的onTap事件,使用原始指针Listener组件来实现会比较复杂。

这时候可以使用自定义一个手势识别器来实现。
参考:Flutter核心技术与实战


wan~
————————————————
版权声明:本文为CSDN博主「_龙衣」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ITxiaodong/article/details/105083031



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!