Flutter 触摸事件监听 Listener 、手势识别示例
指针事件Listener手势识别GestureDetectorGestureRecognizer滑动冲突为了让父容器也能接收到手势,我们需要同时使用 RawGestureDetector 和 GestureFactory,来改变竞技场决定由谁来响应用户事件的结果。手势冲突只是手势级别的,而手势是对原始指针的语义化的识别,所以在遇到复杂的冲突场景时,都可以通过Listener直接识别原...
文章目录
在
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
})
手势识别 GestureDetector
检测手势的
widget
。被GestureDetector
包裹的widget
,可以很方便的监听到手势相关操作。如:单击、双击、长按等。
查看构造函数支持的属性:
GestureDetector({
Key key,
this.child,
this.onTapDown,// 点击按下时
this.onTapUp,// 点击抬起时
this.onTap,// 点击
this.onTapCancel,// 点击取消
this.onSecondaryTapDown,
this.onSecondaryTapUp,
this.onSecondaryTapCancel,
this.onDoubleTap,// 双击
this.onLongPress,// 长按
this.onLongPressStart,// 长按开始
this.onLongPressMoveUpdate,// 长按移动更新
this.onLongPressUp,// 长按抬起
this.onLongPressEnd,// 长按结束
this.onVerticalDragDown,// 垂直移动回调,不能与 onScale,onPan,同时使用
this.onVerticalDragStart,
this.onVerticalDragUpdate,
this.onVerticalDragEnd,
this.onVerticalDragCancel,
this.onHorizontalDragDown,// 水平移动回调,不能与 onScale,onPan,同时使用
this.onHorizontalDragStart,
this.onHorizontalDragUpdate,
this.onHorizontalDragEnd,
this.onHorizontalDragCancel,
this.onForcePressStart,// 按压力开始
this.onForcePressPeak,// 按压力顶峰
this.onForcePressUpdate,
this.onForcePressEnd,
this.onPanDown,// 移动按下,不能与 onScale,onVerticalDrag,onHorizontalDrag,同时使用
this.onPanStart,// 移动开始
this.onPanUpdate,
this.onPanEnd,
this.onPanCancel,
this.onScaleStart,// 缩放开始,不能与 onPan ,onVerticalDrag,onHorizontalDrag,同时使用
this.onScaleUpdate,
this.onScaleEnd,
this.behavior,// 此手势检测器在命中测试期间应如何表现。HitTestBehavior 枚举值:deferToChild,opaque,translucent
this.excludeFromSemantics = false,// 是否从语义树中排除这些手势。
this.dragStartBehavior = DragStartBehavior.start,// 确定处理拖动开始行为的方式。枚举值:down,start
})
需要注意的是:
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~
更多推荐
所有评论(0)