监听UserScrollNotification事件,列表滚动到顶部后,关闭bottomSheet

367 阅读2分钟

下面是一个更新后的例子,显示了如何使用NotificationListener包裹直接使用的底部弹出层:


Get.bottomSheet(
  NotificationListener<UserScrollNotification>(
    NotificationListener<UserScrollNotification>(
    onNotification: (notification) {
      if (notification.direction == ScrollDirection.forward &&
          notification.metrics.extentBefore == 0) {
        // 检查是否向下滑动到顶部
        Get.back(); // 关闭bottomSheet
        return true; // 消费事件,防止继续向上传递
      }
      return false;
    },
    child: Container(
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(16),
          topRight: Radius.circular(16),
        ),
      ),
      child: ListView.builder(
        //... ListView设置不变
      ),
    ),
  ),
  isScrollControlled: true,
);

UserScrollNotification中,direction属性是一个ScrollDirection值,其中ScrollDirection.forward表示用户正在向上滚动。metrics.pixels代表当前滚动的位置,metrics.minScrollExtent代表可滚动内容的最顶端,若两者相等则表示滚动视图已经处于顶部。

OverscrollNotification

在Flutter中,OverscrollNotification是一个继承自ScrollNotification的特定类型的通知,用于表示滚动组件在到达滚动范围的开始或结束位置时的行为。OverscrollNotification在滚动视图被拖拽时,尤其是当内容已经滚动到最大或最小范围并且用户继续尝试滚动时会被触发。

主要属性

  • metrics:当前滚动位置的描述,包含了总滚动范围、当前位置等信息。
  • context:通知发生时的构建上下文。
  • overscroll:超出边界的滚动距离,一个正值通常表示在开始位置向下滚动溢出,一个负值表示在结束位置向上溢出。
  • velocity:滚动动作的速度。

使用场景

通常在需要处理或响应滚动范围溢出的情况下使用,例如实现自定义的下拉刷新或上拉加载更多的功能。

示例代码

以下示例代码展示如何监听 OverscrollNotification

NotificationListener<OverscrollNotification>(
  onNotification: (OverscrollNotification notification) {
    if (notification.overscroll > 0) {
        // 当overscroll为正值时,说明用户在顶部下拉
        print('Reach the top and over scrolling. Overscroll: ${notification.overscroll}');
    } else {
        // 当overscroll为负值时,说明用户在底部上拉
        print('Reach the bottom and over scolling. Overscroll: ${notification.overscroll}');
    }

    // 返回true来取消冒泡,阻止通知上升至父级
    return true;
  },
  child: ListView.builder(
    itemCount: 100,
    itemBuilder: (context, index) {
      return ListTile(title: Text('Item $index'));
    },
  ),
)

在这个例子中,我们使用NotificationListener包裹了ListView.builder,然后监听OverscrollNotification来检测用户在列表的顶部或底部继续滚动(超额滚动)的动作。在onNotification回调函数中,我们根据notification.overscroll的值来判断是在顶部溢出还是在底部溢出,并打印相应的信息。

值得注意的是,OverscrollNotification和其他滚动通知(如ScrollStartNotificationScrollUpdateNotificationScrollEndNotification)一样,可以通过NotificationListener来监听。这使得我们能够在滚动行为中加入自定义逻辑,并根据实际的滚动情况作出响应。

当返回值为true时,会阻止通知继续向上冒泡到上层的Widget;返回false时,通知会继续传播,允许上层Widget也可以对该通知做出响应。

这种处理OverscrollNotification的方式适用于各种滚动视图,如ListViewGridViewCustomScrollView等,允许开发者实现诸如自定义“拉动刷新”、“滚动到底部加载更多”等行为。

UserScrollNotification

在Flutter中,UserScrollNotification是一个特定类型的ScrollNotification,它会在用户直接通过触摸手势改变滚动视图的滚动位置时派发。UserScrollNotification通常用于检测用户的滚动行为,比如当页面开始滚动、结束滚动,或者滚动方向发生改变时。

主要属性

  • metrics:包含当前滚动位置、滚动范围等信息的ScrollMetrics对象。
  • context:发出通知时的BuildContext
  • direction:当前用户滚动的方向,用ScrollDirection枚举表示。可能的值包括forward(向前滚动)、reverse(向后滚动)和idle(停止滚动)。

使用场景

UserScrollNotification用于区分滚动行为是由用户直接引起的,还是由其他滚动控制行为(例如通过代码控制滚动)引起的。这对于想要响应用户主动操作而不是程序触发的滚动时非常有用。

示例代码

以下代码展示了如何使用NotificationListener监听UserScrollNotification并响应用户滚动行为:

NotificationListener<UserScrollNotification>(
  onNotification: (UserScrollNotification notification) {
    if (notification.direction == ScrollDirection.forward) {
      // 用户向前滚动(向下滚动列表)
      print('User is scrolling down');
    } else if (notification.direction == ScrollDirection.reverse) {
      // 用户向后滚动(向上滚动列表)
      print('User is scrolling up');
    } else if (notification.direction == ScrollDirection.idle) {
      // 滚动停止
      print('User scroll has stopped');
    }
    // 返回false允许通知继续传递
    return false;
  },
  child: ListView.builder(
    itemCount: 100,
    itemBuilder: (context, index) {
      return ListTile(title: Text('Item $index'));
  ),
)

在这个示例中,NotificationListener用于监听UserScrollNotification,并通过onNotification回调函数来响应这些通知。

  • 当用户在ListView中向下滚动时,notification.direction将会是ScrollDirection.forward
  • 当用户向上滚动时,notification.direction将会是ScrollDirection.reverse
  • 当用户停止滚动时,notification.direction将会是ScrollDirection.idle

每次滚动通知发生在正在滚动的视图之内时,这个onNotification函数都会被触发,并提供有关当前滚动状态的信息。这可以用于实现一些用户体验增强的特性,比如隐藏或显示工具栏、实现"粘性"头部效果、添加自定义滚动连接动画等。

onNotification回调中返回false代表通知将继续向上传递,这样父组件也有机会响应这些滚动通知。如果你想阻止通知继续传播,可以返回true

请记住,虽然这里的例子使用的是ListView.builderUserScrollNotification同样适用于其他滚动组件,比如SingleChildScrollViewGridViewCustomScrollView等,以监控和响应用户的滚动行为。