diff --git a/CHANGELOG.md b/CHANGELOG.md index 43e05dd8..1bfd69c6 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 showWeekTileBorder field whether to show border for header in month view. [#306](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/306) - Fixed an issue related to hiding day, which is not in the current month in MonthView. [#328](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/328) - Added header title for full day events in week view. [#308](https://github.com/SimformSolutionsPvtLtd/flutter_calendar_view/issues/308) diff --git a/README.md b/README.md index 52a0b364..b9b5386d 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,8 @@ DayView( hourLinePainter: (lineColor, lineHeight, offset, minuteHeight, showVerticalLine, verticalLineOffset) { return //Your custom painter. }, - dayTitleBuilder: DayHeader.hidden // To Hide day header + dayTitleBuilder: DayHeader.hidden, // To Hide day header + keepScrollOffset: true, // To maintain scroll offset when the page changes ); ``` @@ -227,6 +228,7 @@ WeekView( textOverflow: TextOverflow.ellipsis, maxLines: 2, ), // To set full day events header text config + keepScrollOffset: true, // To maintain scroll offset when the page changes ); ``` diff --git a/lib/src/day_view/_internal_day_view_page.dart b/lib/src/day_view/_internal_day_view_page.dart index d7c9607e..804ea239 100644 --- a/lib/src/day_view/_internal_day_view_page.dart +++ b/lib/src/day_view/_internal_day_view_page.dart @@ -14,7 +14,7 @@ import '../painters.dart'; import '../typedefs.dart'; /// Defines a single day page. -class InternalDayViewPage extends StatelessWidget { +class InternalDayViewPage extends StatefulWidget { /// Width of the page final double width; @@ -101,6 +101,8 @@ class InternalDayViewPage extends StatelessWidget { /// Display full day events. final FullDayEventBuilder fullDayEventBuilder; + final ScrollController dayViewScrollController; + /// Flag to display half hours. final bool showHalfHours; @@ -116,7 +118,11 @@ class InternalDayViewPage extends StatelessWidget { /// Settings for half hour indicator lines. final HourIndicatorSettings quarterHourIndicatorSettings; - final ScrollController scrollController; + /// Scroll listener to set every page's last offset + final void Function(ScrollController) scrollListener; + + /// Last scroll offset of day view page. + final double lastScrollOffset; /// Emulate vertical line offset from hour line starts. final double emulateVerticalOffsetBy; @@ -124,6 +130,9 @@ class InternalDayViewPage extends StatelessWidget { /// 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, @@ -151,7 +160,9 @@ class InternalDayViewPage extends StatelessWidget { required this.minuteSlotSize, required this.scrollNotifier, required this.fullDayEventBuilder, - required this.scrollController, + required this.dayViewScrollController, + required this.scrollListener, + this.lastScrollOffset = 0.0, required this.dayDetectorBuilder, required this.showHalfHours, required this.showQuarterHours, @@ -161,130 +172,173 @@ class InternalDayViewPage extends StatelessWidget { required this.quarterHourIndicatorSettings, required this.emulateVerticalOffsetBy, required this.onTileDoubleTap, + this.keepScrollOffset = false, }) : super(key: key); + @override + State createState() => _InternalDayViewPageState(); +} + +class _InternalDayViewPageState + extends State> { + late ScrollController scrollController; + + @override + void initState() { + super.initState(); + scrollController = ScrollController( + initialScrollOffset: widget.lastScrollOffset, + ); + scrollController.addListener(_scrollControllerListener); + } + + @override + void dispose() { + scrollController + ..removeListener(_scrollControllerListener) + ..dispose(); + super.dispose(); + } + + void _scrollControllerListener() { + widget.scrollListener(scrollController); + } + @override Widget build(BuildContext context) { - final fullDayEventList = controller.getFullDayEvent(date); + final fullDayEventList = widget.controller.getFullDayEvent(widget.date); return Container( - height: height, - width: width, + height: widget.height, + width: widget.width, child: Column( children: [ fullDayEventList.isEmpty ? SizedBox.shrink() - : fullDayEventBuilder(fullDayEventList, date), + : widget.fullDayEventBuilder( + widget.controller.getFullDayEvent(widget.date), + widget.date, + ), Expanded( child: SingleChildScrollView( - controller: scrollController, + controller: widget.keepScrollOffset + ? scrollController + : widget.dayViewScrollController, child: SizedBox( - height: height, - width: width, + height: widget.height, + width: widget.width, child: Stack( children: [ CustomPaint( - size: Size(width, height), + size: Size(widget.width, widget.height), painter: HourLinePainter( - lineColor: hourIndicatorSettings.color, - lineHeight: hourIndicatorSettings.height, - offset: timeLineWidth + hourIndicatorSettings.offset, - minuteHeight: heightPerMinute, - verticalLineOffset: verticalLineOffset, - showVerticalLine: showVerticalLine, - lineStyle: hourIndicatorSettings.lineStyle, - dashWidth: hourIndicatorSettings.dashWidth, - dashSpaceWidth: hourIndicatorSettings.dashSpaceWidth, - emulateVerticalOffsetBy: emulateVerticalOffsetBy, - startHour: startHour, - endHour: endHour, + lineColor: widget.hourIndicatorSettings.color, + lineHeight: widget.hourIndicatorSettings.height, + offset: widget.timeLineWidth + + widget.hourIndicatorSettings.offset, + minuteHeight: widget.heightPerMinute, + verticalLineOffset: widget.verticalLineOffset, + showVerticalLine: widget.showVerticalLine, + 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, - endHour: endHour, + widget.halfHourIndicatorSettings.dashSpaceWidth, + startHour: widget.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, ), ), - 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: height, - date: date, - onTileLongTap: onTileLongTap, - onTileDoubleTap: onTileDoubleTap, - onTileTap: onTileTap, - eventArranger: eventArranger, - events: controller.getEventsOnDay( - date, + height: widget.height, + date: widget.date, + onTileLongTap: widget.onTileLongTap, + onTileDoubleTap: widget.onTileDoubleTap, + onTileTap: widget.onTileTap, + eventArranger: widget.eventArranger, + events: widget.controller.getEventsOnDay( + widget.date, includeFullDayEvents: false, ), - heightPerMinute: heightPerMinute, - eventTileBuilder: eventTileBuilder, - scrollNotifier: scrollNotifier, - startHour: startHour, - endHour: endHour, - width: width - - timeLineWidth - - hourIndicatorSettings.offset - - verticalLineOffset, + heightPerMinute: widget.heightPerMinute, + eventTileBuilder: widget.eventTileBuilder, + scrollNotifier: widget.scrollNotifier, + startHour: widget.startHour, + endHour: widget.endHour, + width: widget.width - + widget.timeLineWidth - + widget.hourIndicatorSettings.offset - + widget.verticalLineOffset, ), ), TimeLine( - height: height, - hourHeight: hourHeight, - timeLineBuilder: timeLineBuilder, - timeLineOffset: timeLineOffset, - timeLineWidth: timeLineWidth, - showHalfHours: showHalfHours, - startHour: startHour, - endHour: endHour, - showQuarterHours: showQuarterHours, - key: ValueKey(heightPerMinute), - liveTimeIndicatorSettings: liveTimeIndicatorSettings, + height: widget.height, + hourHeight: widget.hourHeight, + timeLineBuilder: widget.timeLineBuilder, + timeLineOffset: widget.timeLineOffset, + timeLineWidth: widget.timeLineWidth, + showHalfHours: widget.showHalfHours, + startHour: widget.startHour, + endHour: widget.endHour, + showQuarterHours: widget.showQuarterHours, + key: ValueKey(widget.heightPerMinute), + liveTimeIndicatorSettings: + widget.liveTimeIndicatorSettings, ), - if (showLiveLine && liveTimeIndicatorSettings.height > 0) + if (widget.showLiveLine && + widget.liveTimeIndicatorSettings.height > 0) IgnorePointer( child: 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/day_view/day_view.dart b/lib/src/day_view/day_view.dart index 7f73c989..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, @@ -309,6 +313,7 @@ class DayViewState extends State> { late double _height; late double _timeLineWidth; late double _hourHeight; + late double _lastScrollOffset; late DateTime _currentDate; late DateTime _maxDate; late DateTime _minDate; @@ -349,6 +354,7 @@ class DayViewState extends State> { @override void initState() { super.initState(); + _lastScrollOffset = widget.scrollOffset ?? 0.0; _reloadCallback = _reload; _setDateRange(); @@ -484,7 +490,6 @@ class DayViewState extends State> { minuteSlotSize: widget.minuteSlotSize, scrollNotifier: _scrollConfiguration, fullDayEventBuilder: _fullDayEventBuilder, - scrollController: _scrollController, showHalfHours: widget.showHalfHours, showQuarterHours: widget.showQuarterHours, halfHourIndicatorSettings: @@ -495,6 +500,10 @@ class DayViewState extends State> { _quarterHourIndicatorSettings, emulateVerticalOffsetBy: widget.emulateVerticalOffsetBy, + lastScrollOffset: _lastScrollOffset, + dayViewScrollController: _scrollController, + scrollListener: _scrollPageListener, + keepScrollOffset: widget.keepScrollOffset, ), ); }, @@ -742,7 +751,9 @@ class DayViewState extends State> { _currentIndex = index; }); } - animateToDuration(widget.startDuration); + if (!widget.keepScrollOffset) { + animateToDuration(widget.startDuration); + } widget.onPageChange?.call(_currentDate, _currentIndex); } @@ -895,6 +906,11 @@ class DayViewState extends State> { /// Returns the current visible date in day view. DateTime get currentDate => DateTime(_currentDate.year, _currentDate.month, _currentDate.day); + + /// Listener for every day page ScrollController + void _scrollPageListener(ScrollController controller) { + _lastScrollOffset = controller.offset; + } } class DayHeader { diff --git a/lib/src/week_view/_internal_week_view_page.dart b/lib/src/week_view/_internal_week_view_page.dart index c56362f1..e3b28255 100644 --- a/lib/src/week_view/_internal_week_view_page.dart +++ b/lib/src/week_view/_internal_week_view_page.dart @@ -15,7 +15,7 @@ import '../painters.dart'; import '../typedefs.dart'; /// A single page for week view. -class InternalWeekViewPage extends StatelessWidget { +class InternalWeekViewPage extends StatefulWidget { /// Width of the page. final double width; @@ -89,8 +89,6 @@ class InternalWeekViewPage extends StatelessWidget { /// Width of week title. final double weekTitleWidth; - final ScrollController scrollController; - /// Called when user taps on event tile. final CellTapCallback? onTileTap; @@ -127,6 +125,8 @@ class InternalWeekViewPage extends StatelessWidget { /// Display full day events. final FullDayEventBuilder fullDayEventBuilder; + final ScrollController weekViewScrollController; + /// First hour displayed in the layout final int startHour; @@ -151,6 +151,15 @@ class InternalWeekViewPage extends StatelessWidget { /// Defines full day events header text config final FullDayHeaderTextConfig fullDayHeaderTextConfig; + /// Scroll listener to set every page's last offset + final void Function(ScrollController) scrollListener; + + /// Last scroll offset of week view page. + final double lastScrollOffset; + + /// Flag to keep scrollOffset of pages on page change + final bool keepScrollOffset; + /// A single page for week view. const InternalWeekViewPage({ Key? key, @@ -177,7 +186,6 @@ class InternalWeekViewPage extends StatelessWidget { required this.eventArranger, required this.verticalLineOffset, required this.weekTitleWidth, - required this.scrollController, required this.onTileTap, required this.onTileLongTap, required this.onDateLongPress, @@ -196,35 +204,70 @@ class InternalWeekViewPage extends StatelessWidget { required this.endHour, this.fullDayHeaderTitle = '', required this.fullDayHeaderTextConfig, + required this.scrollListener, + required this.weekViewScrollController, + this.lastScrollOffset = 0.0, + this.keepScrollOffset = false, }) : super(key: key); + @override + State createState() => _InternalWeekViewPageState(); +} + +class _InternalWeekViewPageState + extends State> { + late ScrollController scrollController; + + @override + void initState() { + super.initState(); + scrollController = ScrollController( + initialScrollOffset: widget.lastScrollOffset, + ); + scrollController.addListener(_scrollControllerListener); + } + + @override + void dispose() { + scrollController + ..removeListener(_scrollControllerListener) + ..dispose(); + super.dispose(); + } + + void _scrollControllerListener() { + widget.scrollListener(scrollController); + } + @override Widget build(BuildContext context) { final filteredDates = _filteredDate(); return Container( - height: height + weekTitleHeight, - width: width, + 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( - width: width, + width: widget.width, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( - height: weekTitleHeight, - width: timeLineWidth + hourIndicatorSettings.offset, - child: weekNumberBuilder.call(filteredDates[0]), + height: widget.weekTitleHeight, + width: widget.timeLineWidth + + widget.hourIndicatorSettings.offset, + child: widget.weekNumberBuilder.call(filteredDates[0]), ), ...List.generate( filteredDates.length, (index) => SizedBox( - height: weekTitleHeight, - width: weekTitleWidth, - child: weekDayBuilder( + height: widget.weekTitleHeight, + width: widget.weekTitleWidth, + child: widget.weekDayBuilder( filteredDates[index], ), ), @@ -237,12 +280,12 @@ class InternalWeekViewPage extends StatelessWidget { height: 1, ), SizedBox( - width: width, + width: widget.width, child: Container( decoration: BoxDecoration( border: Border( bottom: BorderSide( - color: hourIndicatorSettings.color, + color: widget.hourIndicatorSettings.color, width: 2, ), ), @@ -250,32 +293,33 @@ class InternalWeekViewPage extends StatelessWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - if (fullDayHeaderTitle.isNotEmpty) + if (widget.fullDayHeaderTitle.isNotEmpty) Container( - width: timeLineWidth + hourIndicatorSettings.offset, + width: widget.timeLineWidth + + widget.hourIndicatorSettings.offset, padding: const EdgeInsets.symmetric( vertical: 2, horizontal: 1, ), child: Text( - fullDayHeaderTitle, - textAlign: fullDayHeaderTextConfig.textAlign, - maxLines: fullDayHeaderTextConfig.maxLines, - overflow: fullDayHeaderTextConfig.textOverflow, + widget.fullDayHeaderTitle, + textAlign: widget.fullDayHeaderTextConfig.textAlign, + maxLines: widget.fullDayHeaderTextConfig.maxLines, + overflow: widget.fullDayHeaderTextConfig.textOverflow, ), ), ...List.generate( filteredDates.length, (index) { - final fullDayEventList = - controller.getFullDayEvent(filteredDates[index]); + final fullDayEventList = widget.controller + .getFullDayEvent(filteredDates[index]); return Container( - width: weekTitleWidth, + width: widget.weekTitleWidth, child: fullDayEventList.isEmpty ? null - : fullDayEventBuilder.call( + : widget.fullDayEventBuilder.call( fullDayEventList, - dates[index], + widget.dates[index], ), ); }, @@ -286,106 +330,115 @@ class InternalWeekViewPage extends StatelessWidget { ), Expanded( child: SingleChildScrollView( - controller: scrollController, + controller: widget.keepScrollOffset + ? scrollController + : widget.weekViewScrollController, child: SizedBox( - height: height, - width: width, + height: widget.height, + width: widget.width, child: Stack( children: [ CustomPaint( - size: Size(width, height), + size: Size(widget.width, widget.height), painter: HourLinePainter( - lineColor: hourIndicatorSettings.color, - lineHeight: hourIndicatorSettings.height, - offset: timeLineWidth + hourIndicatorSettings.offset, - minuteHeight: heightPerMinute, - verticalLineOffset: verticalLineOffset, - showVerticalLine: showVerticalLine, - startHour: startHour, - emulateVerticalOffsetBy: emulateVerticalOffsetBy, - endHour: endHour, + lineColor: widget.hourIndicatorSettings.color, + lineHeight: widget.hourIndicatorSettings.height, + offset: widget.timeLineWidth + + widget.hourIndicatorSettings.offset, + minuteHeight: widget.heightPerMinute, + verticalLineOffset: widget.verticalLineOffset, + showVerticalLine: widget.showVerticalLine, + 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( alignment: Alignment.centerRight, child: SizedBox( - width: weekTitleWidth * filteredDates.length, - height: height, + width: widget.weekTitleWidth * filteredDates.length, + height: widget.height, child: Row( children: [ ...List.generate( filteredDates.length, (index) => Container( - decoration: showVerticalLine + decoration: widget.showVerticalLine ? BoxDecoration( border: Border( right: BorderSide( - color: hourIndicatorSettings.color, - width: hourIndicatorSettings.height, + color: widget + .hourIndicatorSettings.color, + width: widget + .hourIndicatorSettings.height, ), ), ) : null, - height: height, - width: weekTitleWidth, + height: widget.height, + 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: height, + height: widget.height, date: filteredDates[index], - onTileTap: onTileTap, - onTileLongTap: onTileLongTap, - onTileDoubleTap: onTileDoubleTap, - width: weekTitleWidth, - eventArranger: eventArranger, - eventTileBuilder: eventTileBuilder, - scrollNotifier: scrollConfiguration, - startHour: startHour, - events: controller.getEventsOnDay( + onTileTap: widget.onTileTap, + onTileLongTap: widget.onTileLongTap, + onTileDoubleTap: widget.onTileDoubleTap, + width: widget.weekTitleWidth, + eventArranger: widget.eventArranger, + eventTileBuilder: widget.eventTileBuilder, + scrollNotifier: + widget.scrollConfiguration, + startHour: widget.startHour, + events: widget.controller.getEventsOnDay( filteredDates[index], includeFullDayEvents: false, ), - heightPerMinute: heightPerMinute, - endHour: endHour, + heightPerMinute: widget.heightPerMinute, + endHour: widget.endHour, ), ], ), @@ -396,26 +449,29 @@ class InternalWeekViewPage extends StatelessWidget { ), ), TimeLine( - timeLineWidth: timeLineWidth, - hourHeight: hourHeight, - height: height, - timeLineOffset: timeLineOffset, - timeLineBuilder: timeLineBuilder, - startHour: startHour, - showHalfHours: showHalfHours, - showQuarterHours: showQuarterHours, - liveTimeIndicatorSettings: liveTimeIndicatorSettings, - endHour: endHour, + timeLineWidth: widget.timeLineWidth, + hourHeight: widget.hourHeight, + height: widget.height, + timeLineOffset: widget.timeLineOffset, + timeLineBuilder: widget.timeLineBuilder, + 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, ), ], ), @@ -430,9 +486,9 @@ class InternalWeekViewPage extends StatelessWidget { List _filteredDate() { final output = []; - final weekDays = this.weekDays.toList(); + final weekDays = widget.weekDays.toList(); - for (final date in dates) { + for (final date in widget.dates) { if (weekDays.any((weekDay) => weekDay.index + 1 == date.weekday)) { output.add(date); } diff --git a/lib/src/week_view/week_view.dart b/lib/src/week_view/week_view.dart index 7f3de723..9b549e6e 100644 --- a/lib/src/week_view/week_view.dart +++ b/lib/src/week_view/week_view.dart @@ -237,6 +237,9 @@ class WeekView extends StatefulWidget { /// Defines full day events header text config final FullDayHeaderTextConfig? fullDayHeaderTextConfig; + /// Flag to keep scrollOffset of pages on page change + final bool keepScrollOffset; + /// Main widget for week view. const WeekView({ Key? key, @@ -294,6 +297,7 @@ class WeekView extends StatefulWidget { this.endHour = Constants.hoursADay, this.fullDayHeaderTitle = '', this.fullDayHeaderTextConfig, + this.keepScrollOffset = false, }) : assert(!(onHeaderTitleTap != null && weekPageHeaderBuilder != null), "can't use [onHeaderTitleTap] & [weekPageHeaderBuilder] simultaneously"), assert((timeLineOffset) >= 0, @@ -328,6 +332,7 @@ class WeekViewState extends State> { late double _height; late double _timeLineWidth; late double _hourHeight; + late double _lastScrollOffset; late DateTime _currentStartDate; late DateTime _currentEndDate; late DateTime _maxDate; @@ -378,6 +383,10 @@ class WeekViewState extends State> { @override void initState() { super.initState(); + _lastScrollOffset = widget.scrollOffset; + + _scrollController = + ScrollController(initialScrollOffset: widget.scrollOffset); _startHour = widget.startHour; _endHour = widget.endHour; @@ -392,8 +401,7 @@ class WeekViewState extends State> { _regulateCurrentDate(); _calculateHeights(); - _scrollController = - ScrollController(initialScrollOffset: widget.scrollOffset); + _pageController = PageController(initialPage: _currentIndex); _eventArranger = widget.eventArranger ?? SideEventArranger(); @@ -533,7 +541,7 @@ class WeekViewState extends State> { showVerticalLine: widget.showVerticalLines, controller: controller, hourHeight: _hourHeight, - scrollController: _scrollController, + weekViewScrollController: _scrollController, eventArranger: _eventArranger, weekDays: _weekDays, minuteSlotSize: widget.minuteSlotSize, @@ -548,6 +556,9 @@ class WeekViewState extends State> { endHour: _endHour, fullDayHeaderTitle: _fullDayHeaderTitle, fullDayHeaderTextConfig: _fullDayHeaderTextConfig, + lastScrollOffset: _lastScrollOffset, + scrollListener: _scrollPageListener, + keepScrollOffset: widget.keepScrollOffset, ), ); }, @@ -993,6 +1004,11 @@ class WeekViewState extends State> { /// Returns true if it does else false. bool _showLiveTimeIndicator(List dates) => dates.any((date) => date.compareWithoutTime(DateTime.now())); + + /// Listener for every week page ScrollController + void _scrollPageListener(ScrollController controller) { + _lastScrollOffset = controller.offset; + } } class WeekHeader {