From 55dee40f14d27665f8094502c36a24735c0df034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C5=82awomir=20Kr=C3=B3l?= Date: Mon, 14 Aug 2023 10:20:21 +0200 Subject: [PATCH 1/2] Extend ScrollOffsetController to current position and scroll without animation --- .../lib/src/scrollable_positioned_list.dart | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/packages/scrollable_positioned_list/lib/src/scrollable_positioned_list.dart b/packages/scrollable_positioned_list/lib/src/scrollable_positioned_list.dart index 60045e9b..0b9f6d09 100644 --- a/packages/scrollable_positioned_list/lib/src/scrollable_positioned_list.dart +++ b/packages/scrollable_positioned_list/lib/src/scrollable_positioned_list.dart @@ -279,12 +279,21 @@ class ItemScrollController { /// This is an experimental API and is subject to change. /// Behavior may be ill-defined in some cases. Please file bugs. class ScrollOffsetController { - Future animateScroll( - {required double offset, - required Duration duration, - Curve curve = Curves.linear}) async { - final currentPosition = - _scrollableListState!.primary.scrollController.offset; + _ScrollablePositionedListState? _scrollableListState; + + void _attach(_ScrollablePositionedListState scrollableListState) { + assert(_scrollableListState == null); + _scrollableListState = scrollableListState; + } + + double get currentPosition => + _scrollableListState!.primary.scrollController.offset; + + Future animateScroll({ + required double offset, + required Duration duration, + Curve curve = Curves.linear, + }) async { final newPosition = currentPosition + offset; await _scrollableListState!.primary.scrollController.animateTo( newPosition, @@ -293,11 +302,13 @@ class ScrollOffsetController { ); } - _ScrollablePositionedListState? _scrollableListState; - - void _attach(_ScrollablePositionedListState scrollableListState) { - assert(_scrollableListState == null); - _scrollableListState = scrollableListState; + void moveScroll({ + required double offset, + }) { + final newPosition = currentPosition + offset; + _scrollableListState!.primary.scrollController.jumpTo( + newPosition, + ); } void _detach() { From 2aad26292eb8ad476bba14e50fc40fdb2c46884a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C5=82awomir=20Kr=C3=B3l?= Date: Mon, 14 Aug 2023 10:31:30 +0200 Subject: [PATCH 2/2] ScrollOffsetController - tests --- .../test/scroll_offset_controller_test.dart | 71 +++++++++++++++---- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/packages/scrollable_positioned_list/test/scroll_offset_controller_test.dart b/packages/scrollable_positioned_list/test/scroll_offset_controller_test.dart index 31ffc7f3..28a57150 100644 --- a/packages/scrollable_positioned_list/test/scroll_offset_controller_test.dart +++ b/packages/scrollable_positioned_list/test/scroll_offset_controller_test.dart @@ -72,7 +72,7 @@ void main() { ); } - testWidgets('Programtically scroll down 50 pixels', + testWidgets('Programmatically scroll down 50 pixels', (WidgetTester tester) async { final scrollDistance = 50.0; @@ -84,7 +84,7 @@ void main() { initialIndex: 5, ); - final originalOffest = tester.getTopLeft(find.text('Item 5')).dy; + final originalOffset = tester.getTopLeft(find.text('Item 5')).dy; unawaited(scrollOffsetController.animateScroll( offset: -scrollDistance, @@ -94,10 +94,10 @@ void main() { final newOffset = tester.getTopLeft(find.text('Item 5')).dy; - expect(newOffset - originalOffest, scrollDistance); + expect(newOffset - originalOffset, scrollDistance); }); - testWidgets('Programtically scroll left 50 pixels', + testWidgets('Programmatically scroll left 50 pixels', (WidgetTester tester) async { final scrollDistance = 50.0; @@ -110,7 +110,7 @@ void main() { scrollDirection: Axis.horizontal, ); - final originalOffest = tester.getTopLeft(find.text('Item 5')).dx; + final originalOffset = tester.getTopLeft(find.text('Item 5')).dx; unawaited(scrollOffsetController.animateScroll( offset: -scrollDistance, @@ -120,10 +120,10 @@ void main() { final newOffset = tester.getTopLeft(find.text('Item 5')).dx; - expect(newOffset - originalOffest, scrollDistance); + expect(newOffset - originalOffset, scrollDistance); }); - testWidgets('Programtically scroll down 50 pixels, stop half way', + testWidgets('Programmatically scroll down 50 pixels, stop half way', (WidgetTester tester) async { final scrollDistance = 50.0; @@ -135,7 +135,7 @@ void main() { initialIndex: 5, ); - final originalOffest = tester.getTopLeft(find.text('Item 5')).dy; + final originalOffset = tester.getTopLeft(find.text('Item 5')).dy; unawaited(scrollOffsetController.animateScroll( offset: -scrollDistance, @@ -150,13 +150,13 @@ void main() { final newOffset = tester.getTopLeft(find.text('Item 5')).dy; - expect(newOffset - originalOffest, scrollDistance ~/ 2); + expect(newOffset - originalOffset, scrollDistance ~/ 2); await tester.pumpAndSettle(); }); testWidgets( - 'Programtically scroll down 50 pixels, stop half way and go back 12', + 'Programmatically scroll down 50 pixels, stop half way and go back 12', (WidgetTester tester) async { final scrollDistance = 50.0; final scrollBack = 12.0; @@ -169,7 +169,7 @@ void main() { initialIndex: 5, ); - final originalOffest = tester.getTopLeft(find.text('Item 5')).dy; + final originalOffset = tester.getTopLeft(find.text('Item 5')).dy; unawaited(scrollOffsetController.animateScroll( offset: -scrollDistance, @@ -187,13 +187,13 @@ void main() { final newOffset = tester.getTopLeft(find.text('Item 5')).dy; - expect(newOffset - originalOffest, (scrollDistance ~/ 2) - scrollBack); + expect(newOffset - originalOffset, (scrollDistance ~/ 2) - scrollBack); await tester.pumpAndSettle(); }); testWidgets( - 'Programtically scroll down 50 pixels, stop half way and then programtically scroll to iten 100', + 'Programmatically scroll down 50 pixels, stop half way and then programmatically scroll to item 100', (WidgetTester tester) async { final scrollDistance = 50.0; @@ -225,4 +225,49 @@ void main() { await tester.pumpAndSettle(); }); + + testWidgets('Programmatically move down 50 pixels', + (WidgetTester tester) async { + final scrollDistance = 50.0; + + ScrollOffsetController scrollOffsetController = ScrollOffsetController(); + + await setUpWidgetTest( + tester, + scrollOffsetController: scrollOffsetController, + initialIndex: 5, + ); + + final originalOffset = tester.getTopLeft(find.text('Item 5')).dy; + + scrollOffsetController.moveScroll( + offset: -scrollDistance, + ); + await tester.pumpAndSettle(); + + final newOffset = tester.getTopLeft(find.text('Item 5')).dy; + + expect(newOffset - originalOffset, scrollDistance); + }); + + testWidgets('Fetch scroll position', (WidgetTester tester) async { + final scrollDistance = 100.0; + + ScrollOffsetController scrollOffsetController = ScrollOffsetController(); + + await setUpWidgetTest( + tester, + scrollOffsetController: scrollOffsetController, + initialIndex: 5, + ); + + expect(scrollOffsetController.currentPosition, isZero); + + scrollOffsetController.moveScroll( + offset: scrollDistance, + ); + await tester.pumpAndSettle(); + + expect(scrollOffsetController.currentPosition, equals(scrollDistance)); + }); }