diff --git a/lib/src/lazy_load_scroll_view.dart b/lib/src/lazy_load_scroll_view.dart index 99eeb861..2bc82a55 100644 --- a/lib/src/lazy_load_scroll_view.dart +++ b/lib/src/lazy_load_scroll_view.dart @@ -15,6 +15,15 @@ class LazyLoadScrollView extends StatefulWidget { /// Called when the [child] reaches the end of the list final AsyncCallback onEndOfPage; + /// Called when the list scrolling starts + final VoidCallback onPageScrollStart; + + /// Called when the list scrolling ends + final VoidCallback onPageScrollEnd; + + /// Called every time the [child] is in-between the list + final VoidCallback onInBetweenOfPage; + /// The offset to take into account when triggering [onEndOfPage]/[onStartOfPage] in pixels final double scrollOffset; @@ -27,6 +36,9 @@ class LazyLoadScrollView extends StatefulWidget { @required this.child, this.onStartOfPage, this.onEndOfPage, + this.onPageScrollStart, + this.onPageScrollEnd, + this.onInBetweenOfPage, this.isLoading = false, this.scrollOffset = 100, }) : assert(child != null), @@ -49,12 +61,34 @@ class _LazyLoadScrollViewState extends State { } bool _onNotification(Notification notification) { + if (notification is ScrollStartNotification) { + if (widget.onPageScrollStart != null) { + widget.onPageScrollStart(); + return true; + } + } + if (notification is ScrollEndNotification) { + if (widget.onPageScrollEnd != null) { + widget.onPageScrollEnd(); + return true; + } + } if (notification is ScrollUpdateNotification) { final pixels = notification.metrics.pixels; - final extentBefore = notification.metrics.extentBefore; - final extentAfter = notification.metrics.extentAfter; + final maxScrollExtent = notification.metrics.maxScrollExtent; + final minScrollExtent = notification.metrics.minScrollExtent; final scrollOffset = widget.scrollOffset; + if (pixels > (minScrollExtent + scrollOffset) && + pixels < (maxScrollExtent - scrollOffset)) { + if (widget.onInBetweenOfPage != null) { + widget.onInBetweenOfPage(); + return true; + } + } + + final extentBefore = notification.metrics.extentBefore; + final extentAfter = notification.metrics.extentAfter; final scrollingDown = _scrollPosition < pixels; if (scrollOffset == null || scrollOffset == 0) { diff --git a/lib/src/message_list_view.dart b/lib/src/message_list_view.dart index 254af757..f4ab3103 100644 --- a/lib/src/message_list_view.dart +++ b/lib/src/message_list_view.dart @@ -212,6 +212,8 @@ class _MessageListViewState extends State { bool initialMessageHighlightComplete = false; + bool _inBetweenList = false; + @override Widget build(BuildContext context) { final streamChannel = StreamChannel.of(context); @@ -264,7 +266,7 @@ class _MessageListViewState extends State { final newMessagesListLength = messages.length; if (_messageListLength != null) { - if (_bottomPaginationActive) { + if (_bottomPaginationActive || (_inBetweenList && _upToDate)) { if (_itemPositionListener.itemPositions.value?.isNotEmpty == true) { final first = _itemPositionListener.itemPositions.value.first; @@ -288,17 +290,27 @@ class _MessageListViewState extends State { children: [ LazyLoadScrollView( onStartOfPage: () async { + _inBetweenList = false; if (!_upToDate) { _topPaginationActive = false; _bottomPaginationActive = true; return _paginateData( - streamChannel, QueryDirection.bottom); + streamChannel, + QueryDirection.bottom, + ); } }, onEndOfPage: () async { + _inBetweenList = false; _topPaginationActive = true; _bottomPaginationActive = false; - return _paginateData(streamChannel, QueryDirection.top); + return _paginateData( + streamChannel, + QueryDirection.top, + ); + }, + onInBetweenOfPage: () { + _inBetweenList = true; }, child: ScrollablePositionedList.builder( key: ValueKey(initialIndex + initialAlignment), @@ -803,6 +815,10 @@ class _MessageListViewState extends State { _messageNewListener = streamChannel.channel.on(EventType.messageNew).listen((event) { + if (_upToDate) { + _bottomPaginationActive = false; + _topPaginationActive = false; + } if (event.message.user.id == streamChannel.channel.client.state.user.id) { WidgetsBinding.instance.addPostFrameCallback((_) { _scrollController.jumpTo(