From 1ec7a2bd01fd644b46a0ad74d8b4f50bea09c86e Mon Sep 17 00:00:00 2001 From: Apurva Kanthraviya Date: Wed, 8 May 2024 15:34:48 +0530 Subject: [PATCH] =?UTF-8?q?fix:=20=F0=9F=90=9B=20added=20support=20to=20ke?= =?UTF-8?q?ep=20scroll=20offset=20while=20scrolling=20in=20day=20and=20wee?= =?UTF-8?q?k=20view.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + lib/src/components/_internal_components.dart | 7 +- lib/src/day_view/_internal_day_view_page.dart | 120 +++++++++------- lib/src/day_view/day_view.dart | 16 ++- .../week_view/_internal_week_view_page.dart | 130 ++++++++++-------- lib/src/week_view/week_view.dart | 10 +- 6 files changed, 168 insertions(+), 116 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d5531f5..8e12f15b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ - # [1.1.1] (UnReleased) +- Fixed synchronization of scroll between pages in day and week view. [#186](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/186) - Added support for double tapping gestures on any event in day, week, and month view. [#195](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/195) - Added support to set end time of day and week view. [#298](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/298) - Added support for horizontal scroll physics of week and month view page. [#314](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/314) diff --git a/lib/src/components/_internal_components.dart b/lib/src/components/_internal_components.dart index 48ce19b3..cebddc29 100644 --- a/lib/src/components/_internal_components.dart +++ b/lib/src/components/_internal_components.dart @@ -98,9 +98,12 @@ class _LiveTimeIndicatorState extends State { /// to set dy offset of live time indicator final startMinutes = widget.startHour * 60; - /// Check if live time is not between startHour and endHour then + /// Check if live time is not between startHour and endHour if it is then /// don't show live time indicator - if (_currentTime.hour > widget.startHour || + /// + /// e.g. startHour : 1:00, endHour : 13:00 and live time is 17:00 + /// then no need to display live time indicator on timeline + if (_currentTime.hour > widget.startHour && widget.endHour < _currentTime.hour) { return SizedBox.shrink(); } diff --git a/lib/src/day_view/_internal_day_view_page.dart b/lib/src/day_view/_internal_day_view_page.dart index cf37908d..545cc610 100644 --- a/lib/src/day_view/_internal_day_view_page.dart +++ b/lib/src/day_view/_internal_day_view_page.dart @@ -101,6 +101,8 @@ class InternalDayViewPage extends StatefulWidget { /// Display full day events. final FullDayEventBuilder fullDayEventBuilder; + final ScrollController dayViewScrollController; + /// Flag to display half hours. final bool showHalfHours; @@ -116,10 +118,11 @@ class InternalDayViewPage extends StatefulWidget { /// Settings for half hour indicator lines. final HourIndicatorSettings quarterHourIndicatorSettings; + /// Scroll listener to set every page's last offset final void Function(ScrollController) scrollListener; - /// Scroll offset of day view page. - final double scrollOffset; + /// Last scroll offset of day view page. + final double lastScrollOffset; /// Emulate vertical line offset from hour line starts. final double emulateVerticalOffsetBy; @@ -127,6 +130,9 @@ class InternalDayViewPage extends StatefulWidget { /// This field will be used to set end hour for day view final int endHour; + /// Flag to keep scrollOffset of pages on page change + final bool keepScrollOffset; + /// Defines a single day page. const InternalDayViewPage({ Key? key, @@ -154,8 +160,9 @@ class InternalDayViewPage extends StatefulWidget { required this.minuteSlotSize, required this.scrollNotifier, required this.fullDayEventBuilder, + required this.dayViewScrollController, required this.scrollListener, - this.scrollOffset = 0.0, + this.lastScrollOffset = 0.0, required this.dayDetectorBuilder, required this.showHalfHours, required this.showQuarterHours, @@ -165,6 +172,7 @@ class InternalDayViewPage extends StatefulWidget { required this.quarterHourIndicatorSettings, required this.emulateVerticalOffsetBy, required this.onTileDoubleTap, + this.keepScrollOffset = false, }) : super(key: key); @override @@ -179,7 +187,7 @@ class _InternalDayViewPageState void initState() { super.initState(); scrollController = ScrollController( - initialScrollOffset: widget.scrollOffset, + initialScrollOffset: widget.lastScrollOffset, ); scrollController.addListener(_scrollControllerListener); } @@ -198,21 +206,23 @@ class _InternalDayViewPageState @override Widget build(BuildContext context) { - final fullDayEventList = controller.getFullDayEvent(date); + final fullDayEventList = widget.controller.getFullDayEvent(widget.date); return Container( height: widget.height, width: widget.width, child: Column( children: [ fullDayEventList.isEmpty - ? SizedBox.shrink() - :widget.fullDayEventBuilder( - widget.controller.getFullDayEvent(widget.date), - widget.date, - ), + ? SizedBox.shrink() + : widget.fullDayEventBuilder( + widget.controller.getFullDayEvent(widget.date), + widget.date, + ), Expanded( child: SingleChildScrollView( - controller: scrollController, + controller: widget.keepScrollOffset + ? scrollController + : widget.dayViewScrollController, child: SizedBox( height: widget.height, width: widget.width, @@ -228,60 +238,63 @@ class _InternalDayViewPageState minuteHeight: widget.heightPerMinute, verticalLineOffset: widget.verticalLineOffset, showVerticalLine: widget.showVerticalLine, - lineStyle: hourIndicatorSettings.lineStyle, - dashWidth: hourIndicatorSettings.dashWidth, - dashSpaceWidth: hourIndicatorSettings.dashSpaceWidth, - emulateVerticalOffsetBy: emulateVerticalOffsetBy, - startHour: startHour, - endHour: endHour, + lineStyle: widget.hourIndicatorSettings.lineStyle, + dashWidth: widget.hourIndicatorSettings.dashWidth, + dashSpaceWidth: widget.hourIndicatorSettings.dashSpaceWidth, + emulateVerticalOffsetBy: widget.emulateVerticalOffsetBy, + startHour: widget.startHour, + endHour: widget.endHour, ), ), - if (showHalfHours) + if (widget.showHalfHours) CustomPaint( - size: Size(width, height), + size: Size(widget.width, widget.height), painter: HalfHourLinePainter( - lineColor: halfHourIndicatorSettings.color, - lineHeight: halfHourIndicatorSettings.height, - offset: - timeLineWidth + halfHourIndicatorSettings.offset, - minuteHeight: heightPerMinute, - lineStyle: halfHourIndicatorSettings.lineStyle, - dashWidth: halfHourIndicatorSettings.dashWidth, + lineColor: widget.halfHourIndicatorSettings.color, + lineHeight: widget.halfHourIndicatorSettings.height, + offset: widget.timeLineWidth + + widget.halfHourIndicatorSettings.offset, + minuteHeight: widget.heightPerMinute, + lineStyle: widget.halfHourIndicatorSettings.lineStyle, + dashWidth: widget.halfHourIndicatorSettings.dashWidth, dashSpaceWidth: - halfHourIndicatorSettings.dashSpaceWidth, - startHour: startHour, + widget.halfHourIndicatorSettings.dashSpaceWidth, + startHour: widget.startHour, endHour: endHour, ), ), - if (showQuarterHours) + if (widget.showQuarterHours) CustomPaint( - size: Size(width, height), + size: Size(widget.width, widget.height), painter: QuarterHourLinePainter( - lineColor: quarterHourIndicatorSettings.color, - lineHeight: quarterHourIndicatorSettings.height, - offset: timeLineWidth + - quarterHourIndicatorSettings.offset, - minuteHeight: heightPerMinute, - lineStyle: quarterHourIndicatorSettings.lineStyle, - dashWidth: quarterHourIndicatorSettings.dashWidth, - dashSpaceWidth: - quarterHourIndicatorSettings.dashSpaceWidth, + lineColor: widget.quarterHourIndicatorSettings.color, + lineHeight: + widget.quarterHourIndicatorSettings.height, + offset: widget.timeLineWidth + + widget.quarterHourIndicatorSettings.offset, + minuteHeight: widget.heightPerMinute, + lineStyle: + widget.quarterHourIndicatorSettings.lineStyle, + dashWidth: + widget.quarterHourIndicatorSettings.dashWidth, + dashSpaceWidth: widget + .quarterHourIndicatorSettings.dashSpaceWidth, ), ), - dayDetectorBuilder( - width: width, - height: height, - heightPerMinute: heightPerMinute, - date: date, - minuteSlotSize: minuteSlotSize, + widget.dayDetectorBuilder( + width: widget.width, + height: widget.height, + heightPerMinute: widget.heightPerMinute, + date: widget.date, + minuteSlotSize: widget.minuteSlotSize, ), Align( alignment: Alignment.centerRight, child: EventGenerator( height: widget.height, date: widget.date, - onTileLongTap: onTileLongTap, - onTileDoubleTap: onTileDoubleTap, + onTileLongTap: widget.onTileLongTap, + onTileDoubleTap: widget.onTileDoubleTap, onTileTap: widget.onTileTap, eventArranger: widget.eventArranger, events: widget.controller.getEventsOnDay( @@ -291,7 +304,7 @@ class _InternalDayViewPageState heightPerMinute: widget.heightPerMinute, eventTileBuilder: widget.eventTileBuilder, scrollNotifier: widget.scrollNotifier, - startHour: startHour, + startHour: widget.startHour, endHour: endHour, width: widget.width - widget.timeLineWidth - @@ -305,12 +318,13 @@ class _InternalDayViewPageState timeLineBuilder: widget.timeLineBuilder, timeLineOffset: widget.timeLineOffset, timeLineWidth: widget.timeLineWidth, - showHalfHours: showHalfHours, - startHour: startHour, + showHalfHours: widget.showHalfHours, + startHour: widget.startHour, endHour: endHour, - showQuarterHours: showQuarterHours, + showQuarterHours: widget.showQuarterHours, key: ValueKey(widget.heightPerMinute), - liveTimeIndicatorSettings: liveTimeIndicatorSettings, + liveTimeIndicatorSettings: + widget.liveTimeIndicatorSettings, ), if (widget.showLiveLine && widget.liveTimeIndicatorSettings.height > 0) @@ -322,7 +336,7 @@ class _InternalDayViewPageState height: widget.height, heightPerMinute: widget.heightPerMinute, timeLineWidth: widget.timeLineWidth, - startHour: startHour, + startHour: widget.startHour, endHour: endHour, ), ), diff --git a/lib/src/day_view/day_view.dart b/lib/src/day_view/day_view.dart index f2c14d83..076025f9 100644 --- a/lib/src/day_view/day_view.dart +++ b/lib/src/day_view/day_view.dart @@ -226,6 +226,9 @@ class DayView extends StatefulWidget { /// This field will be used to set end hour for day view final int endHour; + /// Flag to keep scrollOffset of pages on page change + final bool keepScrollOffset; + /// Main widget for day view. const DayView({ Key? key, @@ -275,6 +278,7 @@ class DayView extends StatefulWidget { this.emulateVerticalOffsetBy = 0, this.onEventDoubleTap, this.endHour = Constants.hoursADay, + this.keepScrollOffset = false, }) : assert(!(onHeaderTitleTap != null && dayTitleBuilder != null), "can't use [onHeaderTitleTap] & [dayTitleBuilder] simultaneously"), assert(timeLineOffset >= 0, @@ -350,7 +354,7 @@ class DayViewState extends State> { @override void initState() { super.initState(); - _lastScrollOffset = widget.scrollOffset; + _lastScrollOffset = widget.scrollOffset ?? 0.0; _reloadCallback = _reload; _setDateRange(); @@ -486,8 +490,6 @@ class DayViewState extends State> { minuteSlotSize: widget.minuteSlotSize, scrollNotifier: _scrollConfiguration, fullDayEventBuilder: _fullDayEventBuilder, - scrollOffset: _lastScrollOffset, - scrollListener: _scrollPageListener, showHalfHours: widget.showHalfHours, showQuarterHours: widget.showQuarterHours, halfHourIndicatorSettings: @@ -498,6 +500,10 @@ class DayViewState extends State> { _quarterHourIndicatorSettings, emulateVerticalOffsetBy: widget.emulateVerticalOffsetBy, + lastScrollOffset: _lastScrollOffset, + dayViewScrollController: _scrollController, + scrollListener: _scrollPageListener, + keepScrollOffset: widget.keepScrollOffset, ), ); }, @@ -745,7 +751,9 @@ class DayViewState extends State> { _currentIndex = index; }); } - animateToDuration(widget.startDuration); + if (!widget.keepScrollOffset) { + animateToDuration(widget.startDuration); + } widget.onPageChange?.call(_currentDate, _currentIndex); } diff --git a/lib/src/week_view/_internal_week_view_page.dart b/lib/src/week_view/_internal_week_view_page.dart index 6f4094b2..4e8a0ef2 100644 --- a/lib/src/week_view/_internal_week_view_page.dart +++ b/lib/src/week_view/_internal_week_view_page.dart @@ -124,6 +124,8 @@ class InternalWeekViewPage extends StatefulWidget { /// Display full day events. final FullDayEventBuilder fullDayEventBuilder; + final ScrollController weekViewScrollController; + /// First hour displayed in the layout final int startHour; @@ -142,11 +144,15 @@ class InternalWeekViewPage extends StatefulWidget { /// This field will be used to set end hour for week view final int endHour; + /// Scroll listener to set every page's last offset final void Function(ScrollController) scrollListener; /// Scroll offset of week view page. final double scrollOffset; + /// Flag to keep scrollOffset of pages on page change + final bool keepScrollOffset; + /// A single page for week view. const InternalWeekViewPage({ Key? key, @@ -190,7 +196,9 @@ class InternalWeekViewPage extends StatefulWidget { required this.onTileDoubleTap, required this.endHour, required this.scrollListener, + required this.weekViewScrollController, this.scrollOffset = 0.0, + this.keepScrollOffset = false, }) : super(key: key); @override @@ -229,8 +237,9 @@ class _InternalWeekViewPageState height: widget.height + widget.weekTitleHeight, width: widget.width, child: Column( - verticalDirection: - showWeekDayAtBottom ? VerticalDirection.up : VerticalDirection.down, + verticalDirection: widget.showWeekDayAtBottom + ? VerticalDirection.up + : VerticalDirection.down, crossAxisAlignment: CrossAxisAlignment.end, children: [ SizedBox( @@ -288,7 +297,9 @@ class _InternalWeekViewPageState ), Expanded( child: SingleChildScrollView( - controller: scrollController, + controller: widget.keepScrollOffset + ? scrollController + : widget.weekViewScrollController, child: SizedBox( height: widget.height, width: widget.width, @@ -304,41 +315,44 @@ class _InternalWeekViewPageState minuteHeight: widget.heightPerMinute, verticalLineOffset: widget.verticalLineOffset, showVerticalLine: widget.showVerticalLine, - startHour: startHour, - emulateVerticalOffsetBy: emulateVerticalOffsetBy, - endHour: endHour, + startHour: widget.startHour, + emulateVerticalOffsetBy: widget.emulateVerticalOffsetBy, + endHour: widget.endHour, ), ), - if (showHalfHours) + if (widget.showHalfHours) CustomPaint( - size: Size(width, height), + size: Size(widget.width, widget.height), painter: HalfHourLinePainter( - lineColor: halfHourIndicatorSettings.color, - lineHeight: halfHourIndicatorSettings.height, - offset: - timeLineWidth + halfHourIndicatorSettings.offset, - minuteHeight: heightPerMinute, - lineStyle: halfHourIndicatorSettings.lineStyle, - dashWidth: halfHourIndicatorSettings.dashWidth, + lineColor: widget.halfHourIndicatorSettings.color, + lineHeight: widget.halfHourIndicatorSettings.height, + offset: widget.timeLineWidth + + widget.halfHourIndicatorSettings.offset, + minuteHeight: widget.heightPerMinute, + lineStyle: widget.halfHourIndicatorSettings.lineStyle, + dashWidth: widget.halfHourIndicatorSettings.dashWidth, dashSpaceWidth: - halfHourIndicatorSettings.dashSpaceWidth, - startHour: halfHourIndicatorSettings.startHour, - endHour: endHour, + widget.halfHourIndicatorSettings.dashSpaceWidth, + startHour: widget.halfHourIndicatorSettings.startHour, + endHour: widget.endHour, ), ), - if (showQuarterHours) + if (widget.showQuarterHours) CustomPaint( - size: Size(width, height), + size: Size(widget.width, widget.height), painter: QuarterHourLinePainter( - lineColor: quarterHourIndicatorSettings.color, - lineHeight: quarterHourIndicatorSettings.height, - offset: timeLineWidth + - quarterHourIndicatorSettings.offset, - minuteHeight: heightPerMinute, - lineStyle: quarterHourIndicatorSettings.lineStyle, - dashWidth: quarterHourIndicatorSettings.dashWidth, - dashSpaceWidth: - quarterHourIndicatorSettings.dashSpaceWidth, + lineColor: widget.quarterHourIndicatorSettings.color, + lineHeight: + widget.quarterHourIndicatorSettings.height, + offset: widget.timeLineWidth + + widget.quarterHourIndicatorSettings.offset, + minuteHeight: widget.heightPerMinute, + lineStyle: + widget.quarterHourIndicatorSettings.lineStyle, + dashWidth: + widget.quarterHourIndicatorSettings.dashWidth, + dashSpaceWidth: widget + .quarterHourIndicatorSettings.dashSpaceWidth, ), ), Align( @@ -351,13 +365,14 @@ class _InternalWeekViewPageState ...List.generate( filteredDates.length, (index) => Container( - decoration: showVerticalLine + decoration: widget.showVerticalLine ? BoxDecoration( border: Border( right: BorderSide( - color: widget.hourIndicatorSettings.color, - width: - widget.hourIndicatorSettings.height, + color: widget + .hourIndicatorSettings.color, + width: widget + .hourIndicatorSettings.height, ), ), ) @@ -366,31 +381,31 @@ class _InternalWeekViewPageState width: widget.weekTitleWidth, child: Stack( children: [ - weekDetectorBuilder( - width: weekTitleWidth, - height: height, - heightPerMinute: heightPerMinute, - date: dates[index], - minuteSlotSize: minuteSlotSize, + widget.weekDetectorBuilder( + width: widget.weekTitleWidth, + height: widget.height, + heightPerMinute: widget.heightPerMinute, + date: widget.dates[index], + minuteSlotSize: widget.minuteSlotSize, ), EventGenerator( height: widget.height, date: filteredDates[index], onTileTap: widget.onTileTap, - onTileLongTap: onTileLongTap, - onTileDoubleTap: onTileDoubleTap, + onTileLongTap: widget.onTileLongTap, + onTileDoubleTap: widget.onTileDoubleTap, width: widget.weekTitleWidth, eventArranger: widget.eventArranger, eventTileBuilder: widget.eventTileBuilder, scrollNotifier: widget.scrollConfiguration, - startHour: startHour, + startHour: widget.startHour, events: widget.controller.getEventsOnDay( filteredDates[index], includeFullDayEvents: false, ), heightPerMinute: widget.heightPerMinute, - endHour: endHour, + endHour: widget.endHour, ), ], ), @@ -406,21 +421,24 @@ class _InternalWeekViewPageState height: widget.height, timeLineOffset: widget.timeLineOffset, timeLineBuilder: widget.timeLineBuilder, - startHour: startHour, - showHalfHours: showHalfHours, - showQuarterHours: showQuarterHours, - liveTimeIndicatorSettings: liveTimeIndicatorSettings, - endHour: endHour, + startHour: widget.startHour, + showHalfHours: widget.showHalfHours, + showQuarterHours: widget.showQuarterHours, + liveTimeIndicatorSettings: + widget.liveTimeIndicatorSettings, + endHour: widget.endHour, ), - if (showLiveLine && liveTimeIndicatorSettings.height > 0) + if (widget.showLiveLine && + widget.liveTimeIndicatorSettings.height > 0) LiveTimeIndicator( - liveTimeIndicatorSettings: liveTimeIndicatorSettings, - width: width, - height: height, - heightPerMinute: heightPerMinute, - timeLineWidth: timeLineWidth, - startHour: startHour, - endHour: endHour, + liveTimeIndicatorSettings: + widget.liveTimeIndicatorSettings, + width: widget.width, + height: widget.height, + heightPerMinute: widget.heightPerMinute, + timeLineWidth: widget.timeLineWidth, + startHour: widget.startHour, + endHour: widget.endHour, ), ], ), diff --git a/lib/src/week_view/week_view.dart b/lib/src/week_view/week_view.dart index b42b9bd6..842fd504 100644 --- a/lib/src/week_view/week_view.dart +++ b/lib/src/week_view/week_view.dart @@ -231,6 +231,9 @@ class WeekView extends StatefulWidget { /// This can be used to disable the horizontal scroll of a page. final ScrollPhysics? pageViewPhysics; + /// Flag to keep scrollOffset of pages on page change + final bool keepScrollOffset; + /// Main widget for week view. const WeekView({ Key? key, @@ -286,6 +289,7 @@ class WeekView extends StatefulWidget { this.pageViewPhysics, this.onEventDoubleTap, this.endHour = Constants.hoursADay, + this.keepScrollOffset = false, }) : assert(!(onHeaderTitleTap != null && weekPageHeaderBuilder != null), "can't use [onHeaderTitleTap] & [weekPageHeaderBuilder] simultaneously"), assert((timeLineOffset) >= 0, @@ -371,6 +375,9 @@ class WeekViewState extends State> { super.initState(); _lastScrollOffset = widget.scrollOffset; + _scrollController = + ScrollController(initialScrollOffset: widget.scrollOffset); + _startHour = widget.startHour; _endHour = widget.endHour; @@ -521,7 +528,7 @@ class WeekViewState extends State> { showVerticalLine: widget.showVerticalLines, controller: controller, hourHeight: _hourHeight, - scrollController: _scrollController, + weekViewScrollController: _scrollController, eventArranger: _eventArranger, weekDays: _weekDays, minuteSlotSize: widget.minuteSlotSize, @@ -536,6 +543,7 @@ class WeekViewState extends State> { endHour: _endHour, scrollOffset: _lastScrollOffset, scrollListener: _scrollPageListener, + keepScrollOffset: widget.keepScrollOffset, ), ); },