Listener 介绍
Listener
它是次要的性能是用来监听屏幕触摸事件,取决于它的子组件区域范畴,比方按下、挪动、抬起、勾销等操作时能够增加监听。
咱们晓得 Flutter
组件只有按钮才会有事件,那么如果我须要在文字或者某个容器上增加事件那我就须要借助Listener
视频教程地址
手势系列视频教程地址
在什么状况下应用 Listener?
Listener
罕用于当手指滑动屏幕时进行暗藏键盘或者下拉刷新、上拉加载时进行事件监听。
个别在理论的开发过程中咱们很少会用到 Listener
来监听手势,个别都是通过 GestureDetector
来进行监听或者应用 MouseRegion
来监听鼠标的事件,而 MouseRegion
罕用于 web 开发中,GestureDetector
罕用于 app。
Listener 原理
- 当指针按下时,Flutter 会对应用程序执行 命中测试(Hit Test),以确定指针与屏幕接触的地位存在哪些组件(widget)
- 指针按下事件(以及该指针的后续事件)而后被散发到由命中测试发现的最外部的组件
- 事件会沿着最外部的组件向组件树的根冒泡散发
- 没有机制勾销或进行“冒泡”过程
Listener 构造函数
咱们常常应用的回调函数次要有三个
- onPointerDown()
- onPointerMove()
- onpointUp()
const Listener({
Key key,
this.onPointerDown,
this.onPointerMove,
// We have to ignore the lint rule here in order to use deprecated
// parameters and keep backward compatibility.
// TODO(tongmu): After it goes stable, remove these 3 parameters from Listener
// and Listener should no longer need an intermediate class _PointerListener.
// https://github.com/flutter/flutter/issues/36085
@Deprecated(
'Use MouseRegion.onEnter instead. See MouseRegion.opaque for behavioral difference.'
'This feature was deprecated after v1.10.14.'
)
this.onPointerEnter,
@Deprecated(
'Use MouseRegion.onExit instead. See MouseRegion.opaque for behavioral difference.'
'This feature was deprecated after v1.10.14.'
)
this.onPointerExit,
@Deprecated(
'Use MouseRegion.onHover instead. See MouseRegion.opaque for behavioral difference.'
'This feature was deprecated after v1.10.14.'
)
this.onPointerHover,
this.onPointerUp,
this.onPointerCancel,
this.onPointerSignal,
this.behavior = HitTestBehavior.deferToChild,
Widget child,
}) : assert(behavior != null),
_child = child,
super(key: key);
Listener 属性和阐明
字段 | 属性 | 形容 |
---|---|---|
onPointerDown | PointerDownEventListener | 指针按下时触发回调 |
onPointerMove | PointerMoveEventListener | 指针挪动时触发回调 |
onPointerUp | PointerUpEventListener | 指针移开时触发回调 |
onPointerSignal | PointerSignalEventListener | 当指针信号呈现时调用 |
onPointerCancel | PointerCancelEventListener | 指针勾销时触发回调 |
onPointerEnter | PointerEnterEventListener | 当指针进入区域时回调(已废除) |
onPointerExit | PointerExitEventListener | 当指针移出区域时回调(已废除) |
onPointerHover | PointerHoverEventListener | 当没有触发 [onPointerDown] 的指针扭转时调用 |
behavior | HitTestBehavior | 在命中测试期间如何体现 |
child | Widget | 子组件 |
Listener 根本应用
咱们这里次要是针对onPointerDown
、onPointerMove
、onPointerUp
进行演示,因为咱们在平时的开发过程中最罕用到的属性就是这三个,而且其余的属性也都被废除掉了。
import 'package:flutter/material.dart';
class ListenerExample extends StatefulWidget {
@override
_ListenerExampleState createState() => _ListenerExampleState();
}
class _ListenerExampleState extends State<ListenerExample> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Listener"),
),
body: Center(
child: Stack(
children: [
Listener(onPointerDown: (event) {print("onPointerDown----$event");
},
onPointerMove: (event) {print("onPointerMove----$event");
},
onPointerUp: (event) {print("onPointerUp----$event");
},
// onPointerSignal: (event) {// print("onPointerSignal----$event");
// },
// onPointerCancel: (event) {// print("onPointerCancel----$event");
// },
// onPointerEnter: (event) {// print("onPointerEnter----$event");
// },
// onPointerExit: (event) {// print("onPointerExit----$event");
// },
// onPointerHover: (event) {// print("onPointerHover----$event");
// },
child: Container(
color: Colors.pink,
child: Text("Jimi",
style: TextStyle(
color: Colors.white,
fontSize: 30
),
),
),
),
Positioned(
child: Listener(onPointerDown: (event) {print("red---- $event");
},
child: Container(
width: 100,
height: 100,
color: Colors.red,
child: Text("Jimi"),
),
),
)
],
),
),
);
}
}
控制台输入
咱们这里先点击橙色容器,在点击一次红色容器,他们打印的后果如下。
flutter: onPointerDown----PointerDownEvent#128be(position: Offset(204.5, 403.5))
flutter: onPointerUp----PointerUpEvent#a9558(position: Offset(204.5, 403.5))
flutter: red---- PointerDownEvent#8ffdf(position: Offset(140.5, 317.0))
PointerEvent 介绍
PointerEvent
是触摸、手写笔、鼠标事件的基类。
在上文中,咱们晓得了什么是 Listener
并写了一个简略的案例,在应用案例的过程中咱们的事件外面都带了一个 event
参数,而所有的事件最终都是继承自 PointerEvent
,那咱们接下来看看event
的参数有什么作用。
PointerEvent 构造函数
const PointerEvent({
this.embedderId = 0,
this.timeStamp = Duration.zero,
this.pointer = 0,
this.kind = PointerDeviceKind.touch,
this.device = 0,
this.position = Offset.zero,
Offset? localPosition,
this.delta = Offset.zero,
Offset? localDelta,
this.buttons = 0,
this.down = false,
this.obscured = false,
this.pressure = 1.0,
this.pressureMin = 1.0,
this.pressureMax = 1.0,
this.distance = 0.0,
this.distanceMax = 0.0,
this.size = 0.0,
this.radiusMajor = 0.0,
this.radiusMinor = 0.0,
this.radiusMin = 0.0,
this.radiusMax = 0.0,
this.orientation = 0.0,
this.tilt = 0.0,
this.platformData = 0,
this.synthesized = false,
this.transform,
this.original,
}) : localPosition = localPosition ?? position,
localDelta = localDelta ?? delta;
PointerEvent 属性和阐明
PointerEvent
的属性十分多,但在咱们理论的开发过程中很少会应用到,只有在特定的情景下才会应用对应的属性。
如须要做一个全局悬浮的按钮咱们会应用到position
如须要做绘图软件咱们须要用到 buttons
、kind
等
所以大家能够依据理论的利用场景来应用对应的属性即可,上面是我对 PointerEvent
的属性进行的一个详细描述。
总共 29 个属性
字段 | 属性 | 形容 |
---|---|---|
embedderId | int | 标识平台事件 ID |
timeStamp | Duration | 事件调度工夫 |
pointer | int | 指针惟一标识符,每一次点击都会是一个新的,不会反复 |
kind | PointerDeviceKind | 指针事件的输出设施类型 |
device | int | 设施惟一标识符,在交互中会重复使用 |
position | Offset | 指针绝对于全局坐标的偏移 |
localPosition | Offset | 指针绝对于以后容器坐标的偏移 |
delta | Offset | 两次指针挪动事件的间隔 |
localDelta | Offset | 两次指针挪动事件的间隔(以后容器) |
buttons | int | 它是 *button 常量,常常与 kind 配合应用,做绘图的画笔软件是常常用到该属性,如果它的值为 6,kind 是 PointerDeviceKind.invertedStylus,那么这示意一个倒置触控笔 |
down | bool | 设置以后指针是否按下 |
obscured | bool | 是否遮挡应用程序的窗口,该属性官网还没实现 |
pressure | double | 按压力度,压力传感器 (如 iPhone 的 3D Touch) 中应用,取值 0.0-1.0 |
pressureMin | double | 按压力度最小值 |
pressureMax | double | 按压力度最大值 |
distance | double | 检测物体与输出外表的间隔 |
distanceMin | double | 限度检测物体与输出外表的间隔最小值 |
distanceMax | double | 限度检测物体与输出外表的间隔最大值 |
size | double | 被按下屏幕的区域大小 |
radiusMajor | double | 接触椭圆沿主轴的半径,以逻辑像素为单位 |
radiusMinor | double | 接触椭圆沿短轴的半径,以逻辑像素为单位 |
radiusMin | double | radiusMajor 和 radiusMinor 报告的最小值 |
radiusMax | double | radiusMajor 和 radiusMinor 报告的最大值 |
orientation | double | 检测到的物体的方向(指针挪动方向),以弧度为单位 |
tilt | double | 检测到的物体的歪斜角度,以弧度为单位 |
platformData | int | 与事件关联的不通明平台特定数据 |
synthesized | bool | 设置事件是否由 Flutter 合成。 |
transform | Matrix4 | 用于从全局坐标转换此事件的转换 |
original | PointerEvent | 在任何 transform 之前的原始未转换 PointerEvent 事件 |
behavior 属性
behavior
属性,它决定子组件如何响应命中测试,它的值类型为HitTestBehavior
,这是一个枚举类,有三个枚举值
HitTestBehavior.deferToChild
对子组件一个接一个的进行命中测试,如果子组件中有测试通过的,则以后组件通过,这就意味着,如果指针事件作用于子组件上时,其父级组件也必定能够收到该事件。
HitTestBehavior.opaque
在命中测试时,将以后组件当成不通明解决(即便自身是通明的),最终的成果相当于以后 Widget 的整个区域都是点击区域
HitTestBehavior.translucent
点击组件通明区域时,能够对本身边界内及底部可视区域都进行命中测试,这意味着点击顶部组件通明区域时,顶部组件和底部组件都能够接管到事件
代码演示
import 'package:flutter/material.dart';
class ListenerSimpleExample extends StatefulWidget {
@override
_ListenerSimpleExampleState createState() => _ListenerSimpleExampleState();
}
class _ListenerSimpleExampleState extends State<ListenerSimpleExample> with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {super.build(context);
return Scaffold(
appBar: AppBar(title: Text("Listener"),
),
body: Center(
child: Stack(
children: [
Listener(
child: ConstrainedBox(constraints: BoxConstraints.tight(Size(400, 200)),
child: Container(color: Colors.greenAccent,)
),
onPointerDown: (event) => print("绿色盒子被点击了"),
),
Listener(
child: ConstrainedBox(constraints: BoxConstraints.tight(Size(400, 200)),
child: Center(child: Text("点击文字", style: TextStyle(
color: Colors.white,
fontSize: 30
),)),
),
onPointerDown: (event) => print("文字点击事件回调"),
behavior: HitTestBehavior.deferToChild,
// behavior: HitTestBehavior.opaque,
// behavior: HitTestBehavior.translucent,
)
],
),
),
);
}
}
当属性设置为 HitTestBehavior.deferToChild 控制台输入后果
咱们这里演示每次都是先点击绿色盒子在点击文字,以便大家能更好的分辨出这三个属性的应用区别
flutter: 绿色盒子被点击了
flutter: 文字点击事件回调
当属性设置为 HitTestBehavior.opaque 控制台输入后果
flutter: 文字点击事件回调
flutter: 文字点击事件回调
当属性设置为 HitTestBehavior.translucent 控制台输入后果
flutter: 文字点击事件回调
flutter: 绿色盒子被点击了
flutter: 文字点击事件回调
总结
Listener
是 Flutter
中比拟重要的功能性组件,它次要的性能是用来监听屏幕触摸事件,事件回调能够获取对应的属性来个性化定制 app 性能。