[Flutter]NotificationListener[ˌnoʊtɪfɪˈkeɪʃn ˈlɪsənər]滑动事件分发
什么是NotificationListener
字面意思是通知监听器,通知基本等价于Android中的事件,所以通知听就可以类比成Android中的事件分发机制。但与Android中任何View都可以处理事件分发不同,Flutter中只有Notification可以监听到通知。所以,当需要对某组件进行通知 监听时,需要用NotificationListener将组件包起来。
怎么又是包起来,在Android中处理事件分发不都是要自定义View吗?实际上Flutter中处处都是自定义Widget,只不过大多数不是通过继承的方式,而是组合。可能仅仅是简简单单的Container包含一个Text,这也算的上是自定义Widget。而当我们给自己的Widget树包裹一层NotificationListener,它就是一个能够处理通知监听的新的Widget了。Compose
支持监听哪些通知
滑动通知
通知在Flutter中的抽象为Notification类,它包含12个子类,对应12种通知,下面将介绍跟主题相关的滑动通知ScrollNotification。滑动通知ScrollNotification有如图五个子类,它们分别代表五种滑动通知,滑动组件触发相应滑动事件时,向Ancestor的NotificationListener发送通知。
滑一滑,看一看,找一找。看看能不能在滑动过程中找到这几个通知。
NotificationListener(
onNotification: (ScrollNotification notification) {
//收到Notification
setState(() {
_currentNotification = notification.runtimeType.toString();//将notification实例的类名展示
});
print(notification.runtimeType.toString());//同时输出log
return true;
},
child: Stack(
children: <Widget>[
ListView.builder(
//...省略
),
Center(child: Text('$_currentNotification'))
],
),
);
找到了,全找到了,ScrollStartNotification–ScrollUpdateNotification–OverScrollNotification–UserScrollNotification–EndScrollNotification,但是有一个疑问,按常理来说,滑动结束时就应该是EndScroll,而实际结果却是UserScroll,当在原地点击的时候,松手时才是EndScroll。于是,看看Log的输出结果吧:
似乎疑惑可以解开了,在滑动结束时,实际上收到了EndScrollNotification,但是被紧跟其后的UserScrollNotification覆盖掉了。通过观察,发现规律,每次滑动的方向发生改变时,就会产生UserScroll事件。而点击过程中的Log也印证了这一点,End前为无方向,End后为无方向,故不会产生UserScroll。
几种滑动通知对应的事件
ScrollStartNotification
当滑动组件开始滑动时,实际上手指接触屏幕那一刻就会触发。
ScrollEndNotification
滑动组件结束滑动时
ScrollUpdateNotification
组件产生位移时
OverscrollNotification
滑动越界时
UserScrollNotification
滑动方向发生改变时
主要属性onNotification(Notification)
来看一下NotificationListener的事件分发源码
可见,分发一个通知有两个条件,一是通知非空,二是通知的类型为T,原来NotificationListener可以指定泛型,这样onNotification方法只会接收到对应事件的回调,不如下面一段代码只会收到滑动结束的通知。
NotificationListener<ScrollEndNotification>(
onNotification: (ScrollNotification notification) {
return