From e17a3c30b790ee493430a51527ed43de528de88a Mon Sep 17 00:00:00 2001 From: Sahil Kumar Date: Thu, 17 Dec 2020 14:42:46 +0530 Subject: [PATCH] [LazyLoadScrollView] Fix callback logic Signed-off-by: Sahil Kumar --- lib/src/lazy_load_scroll_view.dart | 89 ++++++++++++++++-------------- lib/src/message_list_view.dart | 11 ++-- 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/lib/src/lazy_load_scroll_view.dart b/lib/src/lazy_load_scroll_view.dart index a3c344aa..99eeb861 100644 --- a/lib/src/lazy_load_scroll_view.dart +++ b/lib/src/lazy_load_scroll_view.dart @@ -15,7 +15,7 @@ class LazyLoadScrollView extends StatefulWidget { /// Called when the [child] reaches the end of the list final AsyncCallback onEndOfPage; - /// The offset to take into account when triggering [onEndOfPage] in pixels + /// The offset to take into account when triggering [onEndOfPage]/[onStartOfPage] in pixels final double scrollOffset; /// Used to determine if loading of new data has finished. You should use set this if you aren't using a FutureBuilder or StreamBuilder @@ -38,6 +38,7 @@ class LazyLoadScrollView extends StatefulWidget { class _LazyLoadScrollViewState extends State { _LoadingStatus _loadMoreStatus = _LoadingStatus.STABLE; + double _scrollPosition = 0.0; @override Widget build(BuildContext context) { @@ -49,59 +50,65 @@ class _LazyLoadScrollViewState extends State { bool _onNotification(Notification notification) { if (notification is ScrollUpdateNotification) { - if (notification.metrics.maxScrollExtent > notification.metrics.pixels && - notification.metrics.maxScrollExtent - notification.metrics.pixels <= - widget.scrollOffset) { - if (_loadMoreStatus != null && - _loadMoreStatus == _LoadingStatus.STABLE) { - _loadMoreStatus = _LoadingStatus.LOADING; - if (widget.onEndOfPage != null) { - widget.onEndOfPage().whenComplete(() { - _loadMoreStatus = _LoadingStatus.STABLE; - }); - } + final pixels = notification.metrics.pixels; + final extentBefore = notification.metrics.extentBefore; + final extentAfter = notification.metrics.extentAfter; + final scrollOffset = widget.scrollOffset; + + final scrollingDown = _scrollPosition < pixels; + + if (scrollOffset == null || scrollOffset == 0) { + if (extentAfter == 0) { + _onEndOfPage(); + } + if (extentBefore == 0) { + _onStartOfPage(); } - } - if (notification.metrics.minScrollExtent < notification.metrics.pixels && - notification.metrics.pixels - notification.metrics.minScrollExtent <= - widget.scrollOffset) { - if (_loadMoreStatus != null && - _loadMoreStatus == _LoadingStatus.STABLE) { - _loadMoreStatus = _LoadingStatus.LOADING; - if (widget.onStartOfPage != null) { - widget.onStartOfPage().whenComplete(() { - _loadMoreStatus = _LoadingStatus.STABLE; - }); + } else { + if (scrollingDown) { + if (extentAfter <= scrollOffset) { + _onEndOfPage(); + } + } else { + if (extentBefore <= scrollOffset) { + _onStartOfPage(); } } } + _scrollPosition = pixels; return true; } if (notification is OverscrollNotification) { if (notification.overscroll > 0) { - if (_loadMoreStatus != null && - _loadMoreStatus == _LoadingStatus.STABLE) { - _loadMoreStatus = _LoadingStatus.LOADING; - if (widget.onEndOfPage != null) { - widget.onEndOfPage().whenComplete(() { - _loadMoreStatus = _LoadingStatus.STABLE; - }); - } - } + _onEndOfPage(); } if (notification.overscroll < 0) { - if (_loadMoreStatus != null && - _loadMoreStatus == _LoadingStatus.STABLE) { - _loadMoreStatus = _LoadingStatus.LOADING; - if (widget.onStartOfPage != null) { - widget.onStartOfPage().whenComplete(() { - _loadMoreStatus = _LoadingStatus.STABLE; - }); - } - } + _onStartOfPage(); } return true; } return false; } + + void _onEndOfPage() { + if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.STABLE) { + _loadMoreStatus = _LoadingStatus.LOADING; + if (widget.onEndOfPage != null) { + widget.onEndOfPage().whenComplete(() { + _loadMoreStatus = _LoadingStatus.STABLE; + }); + } + } + } + + void _onStartOfPage() { + if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.STABLE) { + _loadMoreStatus = _LoadingStatus.LOADING; + if (widget.onStartOfPage != null) { + widget.onStartOfPage().whenComplete(() { + _loadMoreStatus = _LoadingStatus.STABLE; + }); + } + } + } } diff --git a/lib/src/message_list_view.dart b/lib/src/message_list_view.dart index 4f40feb1..d8a9d416 100644 --- a/lib/src/message_list_view.dart +++ b/lib/src/message_list_view.dart @@ -294,13 +294,13 @@ class _MessageListViewState extends State { if (!_upToDate) { _topPaginationActive = false; _bottomPaginationActive = true; - _paginateData(streamChannel, QueryDirection.bottom); + return _paginateData(streamChannel, QueryDirection.bottom); } }, onEndOfPage: () async { _topPaginationActive = true; _bottomPaginationActive = false; - _paginateData(streamChannel, QueryDirection.top); + return _paginateData(streamChannel, QueryDirection.top); }, child: ScrollablePositionedList.builder( key: ValueKey(initialIndex + initialAlignment), @@ -453,11 +453,12 @@ class _MessageListViewState extends State { }); } - void _paginateData(StreamChannelState channel, QueryDirection direction) { + Future _paginateData( + StreamChannelState channel, QueryDirection direction) { if (widget.parentMessage == null) { - channel.queryMessages(direction: direction); + return channel.queryMessages(direction: direction); } else { - channel.getReplies(widget.parentMessage.id); + return channel.getReplies(widget.parentMessage.id); } }