@@ -486,13 +486,23 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
486486 /// Provides data for rendering events and tracks event changes.
487487 EventController <T >? _controller;
488488
489- /// Scroll controller for managing vertical scrolling within the day view.
490- /// Controls scroll position for time axis (top-to-bottom).
491- late ZoomScrollController _scrollController;
489+ /// Per-page scroll offset cache keyed by page index.
490+ final Map <int , double > _pageOffsets = < int , double > {};
491+
492+ /// Currently visible page scroll controller.
493+ ZoomScrollController ? _activeScrollController;
492494
493495 /// Public getter for accessing the scroll controller.
494496 /// Allows external code to control or listen to scroll events.
495- ScrollController get scrollController => _scrollController;
497+ ZoomScrollController get scrollController {
498+ final controller = _activeScrollController;
499+ if (controller == null || ! controller.hasClients) {
500+ throw StateError (
501+ "ScrollController is not attached to any scroll views yet." ,
502+ );
503+ }
504+ return controller;
505+ }
496506
497507 /// Callback function triggered when the controller changes or events are modified.
498508 /// Used to rebuild the view when event data changes.
@@ -505,8 +515,7 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
505515 @override
506516 void initState () {
507517 super .initState ();
508- _lastScrollOffset = widget.scrollOffset ??
509- widget.startDuration.inMinutes * widget.heightPerMinute;
518+ _lastScrollOffset = _defaultPageOffset;
510519
511520 _reloadCallback = _reload;
512521 _setDateRange ();
@@ -516,10 +525,8 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
516525 _regulateCurrentDate ();
517526
518527 _calculateHeights ();
519- _scrollController = ZoomScrollController (
520- initialScrollOffset: _lastScrollOffset,
521- );
522528 _pageController = PageController (initialPage: _currentIndex);
529+ _pageOffsets[_currentIndex] = _lastScrollOffset;
523530 _eventArranger = widget.eventArranger ?? SideEventArranger <T >();
524531 _assignBuilders ();
525532 }
@@ -562,6 +569,8 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
562569 widget.maxDay != oldWidget.maxDay) {
563570 _setDateRange ();
564571 _regulateCurrentDate ();
572+ _pageOffsets.clear ();
573+ _pageOffsets[_currentIndex] = _defaultPageOffset;
565574
566575 _pageController.jumpToPage (_currentIndex);
567576 }
@@ -575,14 +584,19 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
575584 _assignBuilders ();
576585
577586 if (widget.heightPerMinute != oldWidget.heightPerMinute) {
578- final currentOffset = _scrollController.hasClients
579- ? _scrollController.offset
580- : _lastScrollOffset;
587+ final activeController = _activeScrollController;
588+ final currentOffset =
589+ activeController != null && activeController.hasClients
590+ ? activeController.offset
591+ : _lastScrollOffset;
581592 final scaledOffset = currentOffset *
582593 widget.heightPerMinute /
583594 (oldWidget.heightPerMinute > 0 ? oldWidget.heightPerMinute : 1.0 );
584595 _lastScrollOffset = scaledOffset;
585- _scrollController.prepareZoomJump (scaledOffset);
596+ _pageOffsets[_currentIndex] = scaledOffset;
597+ if (activeController != null && activeController.hasClients) {
598+ activeController.prepareZoomJump (scaledOffset);
599+ }
586600 }
587601 }
588602
@@ -668,9 +682,12 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
668682 _quarterHourIndicatorSettings,
669683 emulateVerticalOffsetBy:
670684 widget.emulateVerticalOffsetBy,
671- lastScrollOffset: _lastScrollOffset,
672- dayViewScrollController: _scrollController,
685+ lastScrollOffset: widget.keepScrollOffset
686+ ? (_pageOffsets[index] ?? _defaultPageOffset)
687+ : _defaultPageOffset,
673688 scrollPhysics: widget.scrollPhysics,
689+ pageIndex: index,
690+ isCurrentPage: index == _currentIndex,
674691 scrollListener: _scrollPageListener,
675692 keepScrollOffset: widget.keepScrollOffset,
676693 timeSlotColorBuilder: _timeSlotColorBuilder,
@@ -951,9 +968,15 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
951968 _currentIndex = index;
952969 });
953970 }
971+ _activeScrollController = null ;
972+ _lastScrollOffset = widget.keepScrollOffset
973+ ? (_pageOffsets[index] ?? _defaultPageOffset)
974+ : _defaultPageOffset;
975+
954976 if (! widget.keepScrollOffset) {
977+ _pageOffsets[index] = _defaultPageOffset;
955978 _jumpToOffsetAfterPageTransition (
956- _offsetForDuration (widget.startDuration). toDouble () ,
979+ _defaultPageOffset ,
957980 );
958981 }
959982 widget.onPageChange? .call (_currentDate, _currentIndex);
@@ -990,24 +1013,46 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
9901013
9911014 void _jumpToOffsetAfterPageTransition (double offset) {
9921015 _runAfterPageTransition (() {
993- if (! _scrollController.hasClients) return ;
1016+ _withAttachedScrollController ((controller) {
1017+ final clampedOffset = offset.clamp (
1018+ controller.position.minScrollExtent,
1019+ controller.position.maxScrollExtent,
1020+ );
9941021
995- final clampedOffset = offset.clamp (
996- _scrollController.position.minScrollExtent,
997- _scrollController.position.maxScrollExtent,
998- );
1022+ _lastScrollOffset = clampedOffset.toDouble ();
1023+ _pageOffsets[_currentIndex] = _lastScrollOffset;
1024+ controller.jumpTo (clampedOffset.toDouble ());
1025+ });
1026+ });
1027+ }
1028+
1029+ void _withAttachedScrollController (
1030+ void Function (ZoomScrollController controller) action,
1031+ ) {
1032+ final controller = _activeScrollController;
1033+ if (controller != null && controller.hasClients) {
1034+ action (controller);
1035+ return ;
1036+ }
9991037
1000- _lastScrollOffset = clampedOffset.toDouble ();
1001- _scrollController.jumpTo (clampedOffset.toDouble ());
1038+ WidgetsBinding .instance.addPostFrameCallback ((_) {
1039+ if (! mounted) return ;
1040+
1041+ final updatedController = _activeScrollController;
1042+ if (updatedController != null && updatedController.hasClients) {
1043+ action (updatedController);
1044+ }
10021045 });
10031046 }
10041047
1048+ double get _defaultPageOffset =>
1049+ widget.scrollOffset ?? _offsetForDuration (widget.startDuration);
1050+
10051051 double _offsetForDuration (Duration startDuration) {
1006- final offSetForSingleMinute = _height / 24 / 60 ;
10071052 final startDurationInMinutes = startDuration.inMinutes;
10081053 final minuteOffset =
10091054 startDurationInMinutes > 3600 ? 3600 : startDurationInMinutes;
1010- return offSetForSingleMinute * minuteOffset;
1055+ return widget.heightPerMinute * minuteOffset;
10111056 }
10121057
10131058 /// Animate to next page (next day).
@@ -1208,20 +1253,32 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
12081253 Duration duration = const Duration (milliseconds: 200 ),
12091254 Curve curve = Curves .linear,
12101255 }) {
1211- _scrollController.animateTo (
1212- offset,
1213- duration: duration,
1214- curve: curve,
1215- );
1256+ _withAttachedScrollController ((controller) {
1257+ controller.animateTo (
1258+ offset,
1259+ duration: duration,
1260+ curve: curve,
1261+ );
1262+ });
12161263 }
12171264
12181265 /// Returns the current visible date in day view.
12191266 DateTime get currentDate =>
12201267 DateTime (_currentDate.year, _currentDate.month, _currentDate.day);
12211268
12221269 /// Listener for every day page ScrollController
1223- void _scrollPageListener (ScrollController controller) {
1224- _lastScrollOffset = controller.offset;
1270+ void _scrollPageListener (
1271+ int pageIndex,
1272+ double offset,
1273+ ZoomScrollController controller,
1274+ ) {
1275+ _activeScrollController = controller;
1276+ if (! widget.keepScrollOffset) return ;
1277+
1278+ _pageOffsets[pageIndex] = offset;
1279+ if (pageIndex == _currentIndex) {
1280+ _lastScrollOffset = offset;
1281+ }
12251282 }
12261283}
12271284
0 commit comments