n2n1 发表于 2023-9-11 17:34:56

Flutter NotificationListener

1.NotificationListener介绍widget通知监听


2.NotificationListener属性
[*]child:widget
[*]onNotification:NotificationListenerCallback,返回值true表示消费掉当前通知不再向上一级NotificationListener传递通知,false则会再向上一级NotificationListener传递通知;这里需要注意的是通知是由下而上去传递的,所以才会称作冒泡通知


3.ScrollNotificationScrollNotification是一个抽象类,它的子类还有:

[*]ScrollStartNotification:滑动开始通知
[*]ScrollUpdateNotification:滑动中通知,滑动过程中会一直回调
[*]ScrollEndNotification:滑动结束通知
[*]OverscrollNotification:滑动位置未改变通知,这个一般只有在滑动到列表边界才会回调,且需要设置不可越界,即physics为ClampingScrollPhysics,这里要注意安卓默认是这样,但是ios平台默认是弹性边界
[*]UserScrollNotification:用户滑动通知,这个跟ScrollUpdateNotification的区别是他指挥有滑动开始后以及滑动结束后回调


4.Notification.ScrollMetrics属性
[*]pixels:当前绝对位置
[*]atEdge:是否在顶部或底部
[*]axis:垂直或水平滚动
[*]axisDirection:滚动方向描述是down还是up,这个受列表reverse影响,正序就是down倒序就是up,并不代表列表是上滑还是下滑
[*]extentAfter:视口底部距离列表底部有多大
[*]extentBefore:视口顶部距离列表顶部有多大
[*]extentInside:视口范围内的列表长度
[*]maxScrollExtent:最大滚动距离,列表长度-视口长度
[*]minScrollExtent:最小滚动距离
[*]viewportDimension:沿滚动方向视口的长度
[*]outOfRange:是否越过边界


4.使用_myChild() {
    return ListView.builder(
      itemBuilder: (context, index) => ListTile(title: Text('item $index')),
      itemCount: 30,
      reverse: true,
      // physics: BouncingScrollPhysics(),
    );
}

@override
Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      title: Text('NotificationListener'),
      ),
      body: NotificationListener<ScrollNotification>(
      onNotification: (notification) {
          ScrollMetrics metrics = notification.metrics;
          print('ScrollNotification####################');
          print('pixels = ${metrics.pixels}');
          print('atEdge = ${metrics.atEdge}');
          print('axis = ${metrics.axis}');
          print('axisDirection = ${metrics.axisDirection}');
          print('extentAfter = ${metrics.extentAfter}');
          print('extentBefore = ${metrics.extentBefore}');
          print('extentInside = ${metrics.extentInside}');
          print('maxScrollExtent = ${metrics.maxScrollExtent}');
          print('minScrollExtent = ${metrics.minScrollExtent}');
          print('viewportDimension = ${metrics.viewportDimension}');
          print('outOfRange = ${metrics.outOfRange}');
          print('ScrollNotification####################');
          return false;
      },
      child: NotificationListener<ScrollUpdateNotification>(
          onNotification: (notification) {
            print('ScrollUpdateNotification####################');
            return false;
          },
          child: NotificationListener<OverscrollNotification>(
            onNotification: (notification) {
            print('OverscrollNotification####################');
            return false;
            },
            child: NotificationListener<ScrollStartNotification>(
            onNotification: (notification) {
                print('ScrollStartNotification####################');
                return false;
            },
            child: NotificationListener<ScrollEndNotification>(
                onNotification: (notification) {
                  print('ScrollEndNotification####################');
                  return false;
                },
                child: _myChild(),
            ),
            ),
          ),
      ),
      ),
    );
}
5.系统提供的其他NotificationNotification是所有通知监听的顶级父类,它的子类有:

[*]LayoutChangedNotification:这是一个空实现子类,他的子类有ScrollNotification,SizeChangedLayoutNotification
[*]SizeChangedLayoutNotification:这是一个空实现子类,一般不会用到
[*]DraggableScrollableNotification:DraggableScrollableSheet的拖拽通知,这个后面再介绍
[*]OverscrollIndicatorNotification:这是滑动指示器的通知监听,例如Scrollbar,需要注意的是这个只有在滑动到头部或者尾部才会回调,而且滑动布局也需要是不可越界的,即physics为ClampingScrollPhysics
这里的代码就在上期Flutter(82):Scroll组件之Scrollbar上修改一下:
[*]

@override
Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      title: Text('Scrollbar'),
      ),
      body: NotificationListener<OverscrollIndicatorNotification>(
      onNotification: (notification) {
          //滑动指示器是否在头部 true在前端,false在末端
          print('${notification.leading}');
          return true;
      },
      child: Scrollbar(
          radius: Radius.circular(10),
          thickness: 10,
          child: ListView.builder(
            itemBuilder: (context, index) {
            return ListTile(
                title: Text('item $index'),
            );
            },
            itemCount: 30,
          ),
      ),
      ),
    );
}
6.自定义Notification这里我们做个简单的演示
@override
Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      title: Text('Scrollbar'),
      ),
      body: NotificationListener<OverscrollIndicatorNotification>(
      onNotification: (notification) {
          //滑动指示器是否在头部 true在前端,false在末端
          print('${notification.leading}');
          return true;
      },
      child: Scrollbar(
          radius: Radius.circular(10),
          thickness: 10,
          child: ListView.builder(
            itemBuilder: (context, index) {
            return ListTile(
                title: Text('item $index'),
            );
            },
            itemCount: 30,
          ),
      ),
      ),
    );
}这里在2级NotificationListener处消费掉当前的通知了,所以不再向1级NotificationListener传递通知了,如果将2级NotificationListener处设置为false,则会传递





页: [1]
查看完整版本: Flutter NotificationListener