@@ -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,18 @@ 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
587+ final activeController = _activeScrollController;
588+ final currentOffset = activeController != null && activeController.hasClients
589+ ? activeController.offset
580590 : _lastScrollOffset;
581591 final scaledOffset = currentOffset *
582592 widget.heightPerMinute /
583593 (oldWidget.heightPerMinute > 0 ? oldWidget.heightPerMinute : 1.0 );
584594 _lastScrollOffset = scaledOffset;
585- _scrollController.prepareZoomJump (scaledOffset);
595+ _pageOffsets[_currentIndex] = scaledOffset;
596+ if (activeController != null && activeController.hasClients) {
597+ activeController.prepareZoomJump (scaledOffset);
598+ }
586599 }
587600 }
588601
@@ -668,9 +681,12 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
668681 _quarterHourIndicatorSettings,
669682 emulateVerticalOffsetBy:
670683 widget.emulateVerticalOffsetBy,
671- lastScrollOffset: _lastScrollOffset,
672- dayViewScrollController: _scrollController,
684+ lastScrollOffset: widget.keepScrollOffset
685+ ? (_pageOffsets[index] ?? _defaultPageOffset)
686+ : _defaultPageOffset,
673687 scrollPhysics: widget.scrollPhysics,
688+ pageIndex: index,
689+ isCurrentPage: index == _currentIndex,
674690 scrollListener: _scrollPageListener,
675691 keepScrollOffset: widget.keepScrollOffset,
676692 timeSlotColorBuilder: _timeSlotColorBuilder,
@@ -951,9 +967,15 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
951967 _currentIndex = index;
952968 });
953969 }
970+ _activeScrollController = null ;
971+ _lastScrollOffset = widget.keepScrollOffset
972+ ? (_pageOffsets[index] ?? _defaultPageOffset)
973+ : _defaultPageOffset;
974+
954975 if (! widget.keepScrollOffset) {
976+ _pageOffsets[index] = _defaultPageOffset;
955977 _jumpToOffsetAfterPageTransition (
956- _offsetForDuration (widget.startDuration). toDouble () ,
978+ _defaultPageOffset ,
957979 );
958980 }
959981 widget.onPageChange? .call (_currentDate, _currentIndex);
@@ -990,24 +1012,46 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
9901012
9911013 void _jumpToOffsetAfterPageTransition (double offset) {
9921014 _runAfterPageTransition (() {
993- if (! _scrollController.hasClients) return ;
1015+ _withAttachedScrollController ((controller) {
1016+ final clampedOffset = offset.clamp (
1017+ controller.position.minScrollExtent,
1018+ controller.position.maxScrollExtent,
1019+ );
9941020
995- final clampedOffset = offset.clamp (
996- _scrollController.position.minScrollExtent,
997- _scrollController.position.maxScrollExtent,
998- );
1021+ _lastScrollOffset = clampedOffset.toDouble ();
1022+ _pageOffsets[_currentIndex] = _lastScrollOffset;
1023+ controller.jumpTo (clampedOffset.toDouble ());
1024+ });
1025+ });
1026+ }
1027+
1028+ void _withAttachedScrollController (
1029+ void Function (ZoomScrollController controller) action,
1030+ ) {
1031+ final controller = _activeScrollController;
1032+ if (controller != null && controller.hasClients) {
1033+ action (controller);
1034+ return ;
1035+ }
9991036
1000- _lastScrollOffset = clampedOffset.toDouble ();
1001- _scrollController.jumpTo (clampedOffset.toDouble ());
1037+ WidgetsBinding .instance.addPostFrameCallback ((_) {
1038+ if (! mounted) return ;
1039+
1040+ final updatedController = _activeScrollController;
1041+ if (updatedController != null && updatedController.hasClients) {
1042+ action (updatedController);
1043+ }
10021044 });
10031045 }
10041046
1047+ double get _defaultPageOffset =>
1048+ widget.scrollOffset ?? _offsetForDuration (widget.startDuration);
1049+
10051050 double _offsetForDuration (Duration startDuration) {
1006- final offSetForSingleMinute = _height / 24 / 60 ;
10071051 final startDurationInMinutes = startDuration.inMinutes;
10081052 final minuteOffset =
10091053 startDurationInMinutes > 3600 ? 3600 : startDurationInMinutes;
1010- return offSetForSingleMinute * minuteOffset;
1054+ return widget.heightPerMinute * minuteOffset;
10111055 }
10121056
10131057 /// Animate to next page (next day).
@@ -1208,20 +1252,32 @@ class DayViewState<T extends Object?> extends State<DayView<T>> {
12081252 Duration duration = const Duration (milliseconds: 200 ),
12091253 Curve curve = Curves .linear,
12101254 }) {
1211- _scrollController.animateTo (
1212- offset,
1213- duration: duration,
1214- curve: curve,
1215- );
1255+ _withAttachedScrollController ((controller) {
1256+ controller.animateTo (
1257+ offset,
1258+ duration: duration,
1259+ curve: curve,
1260+ );
1261+ });
12161262 }
12171263
12181264 /// Returns the current visible date in day view.
12191265 DateTime get currentDate =>
12201266 DateTime (_currentDate.year, _currentDate.month, _currentDate.day);
12211267
12221268 /// Listener for every day page ScrollController
1223- void _scrollPageListener (ScrollController controller) {
1224- _lastScrollOffset = controller.offset;
1269+ void _scrollPageListener (
1270+ int pageIndex,
1271+ double offset,
1272+ ZoomScrollController controller,
1273+ ) {
1274+ _activeScrollController = controller;
1275+ if (! widget.keepScrollOffset) return ;
1276+
1277+ _pageOffsets[pageIndex] = offset;
1278+ if (pageIndex == _currentIndex) {
1279+ _lastScrollOffset = offset;
1280+ }
12251281 }
12261282}
12271283
0 commit comments