From 67706d43b5c2d93c6ec5c8231de4d784c64f6c59 Mon Sep 17 00:00:00 2001 From: Fernando Luis Date: Fri, 10 Feb 2023 23:42:56 -0600 Subject: [PATCH 1/2] Synchronize InternalDayViewPage scroll --- lib/src/day_view/_internal_day_view_page.dart | 131 ++++++++++++------ lib/src/day_view/day_view.dart | 15 +- 2 files changed, 95 insertions(+), 51 deletions(-) diff --git a/lib/src/day_view/_internal_day_view_page.dart b/lib/src/day_view/_internal_day_view_page.dart index 36e037b0..74e15ca4 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; @@ -89,7 +89,10 @@ class InternalDayViewPage extends StatelessWidget { /// Display full day events. final FullDayEventBuilder fullDayEventBuilder; - final ScrollController scrollController; + final void Function(ScrollController) scrollListener; + + /// Scroll offset of day view page. + final double scrollOffset; /// Defines a single day page. const InternalDayViewPage({ @@ -116,78 +119,114 @@ class InternalDayViewPage extends StatelessWidget { required this.minuteSlotSize, required this.scrollNotifier, required this.fullDayEventBuilder, - required this.scrollController, + required this.scrollListener, + this.scrollOffset = 0.0, }) : super(key: key); + @override + State createState() => _InternalDayViewPageState(); +} + +class _InternalDayViewPageState + extends State> { + late ScrollController scrollController; + + @override + void initState() { + super.initState(); + scrollController = ScrollController( + initialScrollOffset: widget.scrollOffset, + ); + scrollController.addListener(_scrollControllerListener); + } + + @override + void dispose() { + scrollController + ..removeListener(_scrollControllerListener) + ..dispose(); + super.dispose(); + } + + void _scrollControllerListener() { + widget.scrollListener(scrollController); + } + @override Widget build(BuildContext context) { return Container( - height: height, - width: width, + height: widget.height, + width: widget.width, child: Column( children: [ - fullDayEventBuilder(controller.getFullDayEvent(date), date), + widget.fullDayEventBuilder( + widget.controller.getFullDayEvent(widget.date), + widget.date, + ), Expanded( child: SingleChildScrollView( controller: scrollController, 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, + lineColor: widget.hourIndicatorSettings.color, + lineHeight: widget.hourIndicatorSettings.height, + offset: widget.timeLineWidth + + widget.hourIndicatorSettings.offset, + minuteHeight: widget.heightPerMinute, + verticalLineOffset: widget.verticalLineOffset, + showVerticalLine: widget.showVerticalLine, ), ), PressDetector( - width: width, - height: height, - heightPerMinute: heightPerMinute, - date: date, - onDateTap: onDateTap, - onDateLongPress: onDateLongPress, - minuteSlotSize: minuteSlotSize, + width: widget.width, + height: widget.height, + heightPerMinute: widget.heightPerMinute, + date: widget.date, + onDateTap: widget.onDateTap, + onDateLongPress: widget.onDateLongPress, + minuteSlotSize: widget.minuteSlotSize, ), Align( alignment: Alignment.centerRight, child: EventGenerator( - height: height, - date: date, - onTileTap: onTileTap, - eventArranger: eventArranger, - events: controller.getEventsOnDay(date), - heightPerMinute: heightPerMinute, - eventTileBuilder: eventTileBuilder, - scrollNotifier: scrollNotifier, - width: width - - timeLineWidth - - hourIndicatorSettings.offset - - verticalLineOffset, + height: widget.height, + date: widget.date, + onTileTap: widget.onTileTap, + eventArranger: widget.eventArranger, + events: widget.controller.getEventsOnDay(widget.date), + heightPerMinute: widget.heightPerMinute, + eventTileBuilder: widget.eventTileBuilder, + scrollNotifier: widget.scrollNotifier, + width: widget.width - + widget.timeLineWidth - + widget.hourIndicatorSettings.offset - + widget.verticalLineOffset, ), ), TimeLine( - height: height, - hourHeight: hourHeight, - timeLineBuilder: timeLineBuilder, - timeLineOffset: timeLineOffset, - timeLineWidth: timeLineWidth, - key: ValueKey(heightPerMinute), + height: widget.height, + hourHeight: widget.hourHeight, + timeLineBuilder: widget.timeLineBuilder, + timeLineOffset: widget.timeLineOffset, + timeLineWidth: widget.timeLineWidth, + key: ValueKey(widget.heightPerMinute), ), - 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, + liveTimeIndicatorSettings: + widget.liveTimeIndicatorSettings, + width: widget.width, + height: widget.height, + heightPerMinute: widget.heightPerMinute, + timeLineWidth: widget.timeLineWidth, ), ), ], diff --git a/lib/src/day_view/day_view.dart b/lib/src/day_view/day_view.dart index d78afb44..6cb70819 100644 --- a/lib/src/day_view/day_view.dart +++ b/lib/src/day_view/day_view.dart @@ -218,6 +218,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; @@ -241,8 +242,6 @@ class DayViewState extends State> { EventController? _controller; - late ScrollController _scrollController; - late VoidCallback _reloadCallback; final _scrollConfiguration = EventScrollConfiguration(); @@ -250,6 +249,7 @@ class DayViewState extends State> { @override void initState() { super.initState(); + _lastScrollOffset = widget.scrollOffset; _reloadCallback = _reload; _setDateRange(); @@ -259,8 +259,7 @@ class DayViewState extends State> { _regulateCurrentDate(); _calculateHeights(); - _scrollController = - ScrollController(initialScrollOffset: widget.scrollOffset); + _pageController = PageController(initialPage: _currentIndex); _eventArranger = widget.eventArranger ?? SideEventArranger(); _assignBuilders(); @@ -381,7 +380,8 @@ class DayViewState extends State> { minuteSlotSize: widget.minuteSlotSize, scrollNotifier: _scrollConfiguration, fullDayEventBuilder: _fullDayEventBuilder, - scrollController: _scrollController, + scrollOffset: _lastScrollOffset, + scrollListener: _scrollPageListener, ), ); }, @@ -677,4 +677,9 @@ 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; + } } From bcbacf0b44981b41a6fec3088d9455f8e45888c2 Mon Sep 17 00:00:00 2001 From: Fernando Luis Date: Fri, 10 Feb 2023 23:56:07 -0600 Subject: [PATCH 2/2] Sinchronize scroll from wekkview --- .../week_view/_internal_week_view_page.dart | 165 +++++++++++------- lib/src/week_view/week_view.dart | 14 +- 2 files changed, 113 insertions(+), 66 deletions(-) diff --git a/lib/src/week_view/_internal_week_view_page.dart b/lib/src/week_view/_internal_week_view_page.dart index 38099de3..21852515 100644 --- a/lib/src/week_view/_internal_week_view_page.dart +++ b/lib/src/week_view/_internal_week_view_page.dart @@ -14,7 +14,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; @@ -76,8 +76,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; @@ -108,6 +106,11 @@ class InternalWeekViewPage extends StatelessWidget { /// Display full day events. final FullDayEventBuilder? fullDayEventBuilder; + final void Function(ScrollController) scrollListener; + + /// Scroll offset of week view page. + final double scrollOffset; + /// A single page for week view. const InternalWeekViewPage({ Key? key, @@ -131,7 +134,6 @@ class InternalWeekViewPage extends StatelessWidget { required this.eventArranger, required this.verticalLineOffset, required this.weekTitleWidth, - required this.scrollController, required this.onTileTap, required this.onDateLongPress, required this.onDateTap, @@ -139,33 +141,65 @@ class InternalWeekViewPage extends StatelessWidget { required this.minuteSlotSize, required this.scrollConfiguration, this.fullDayEventBuilder, + required this.scrollListener, + this.scrollOffset = 0.0, }) : super(key: key); + @override + State createState() => _InternalWeekViewPageState(); +} + +class _InternalWeekViewPageState + extends State> { + late ScrollController scrollController; + + @override + void initState() { + super.initState(); + scrollController = ScrollController( + initialScrollOffset: widget.scrollOffset, + ); + 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( 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], ), ), @@ -178,18 +212,20 @@ class InternalWeekViewPage extends StatelessWidget { height: 1, ), SizedBox( - width: width, + width: widget.width, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox(width: timeLineWidth + hourIndicatorSettings.offset), + SizedBox( + width: widget.timeLineWidth + + widget.hourIndicatorSettings.offset), ...List.generate( filteredDates.length, (index) => SizedBox( - width: weekTitleWidth, - child: fullDayEventBuilder?.call( - controller.getFullDayEvent(filteredDates[index]), - dates[index], + width: widget.weekTitleWidth, + child: widget.fullDayEventBuilder?.call( + widget.controller.getFullDayEvent(filteredDates[index]), + widget.dates[index], ), ), ) @@ -200,34 +236,37 @@ class InternalWeekViewPage extends StatelessWidget { child: SingleChildScrollView( controller: scrollController, 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, + lineColor: widget.hourIndicatorSettings.color, + lineHeight: widget.hourIndicatorSettings.height, + offset: widget.timeLineWidth + + widget.hourIndicatorSettings.offset, + minuteHeight: widget.heightPerMinute, + verticalLineOffset: widget.verticalLineOffset, + showVerticalLine: widget.showVerticalLine, ), ), - if (showLiveLine && liveTimeIndicatorSettings.height > 0) + if (widget.showLiveLine && + widget.liveTimeIndicatorSettings.height > 0) LiveTimeIndicator( - liveTimeIndicatorSettings: liveTimeIndicatorSettings, - width: width, - height: height, - heightPerMinute: heightPerMinute, - timeLineWidth: timeLineWidth, + liveTimeIndicatorSettings: + widget.liveTimeIndicatorSettings, + width: widget.width, + height: widget.height, + heightPerMinute: widget.heightPerMinute, + timeLineWidth: widget.timeLineWidth, ), 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( @@ -236,35 +275,37 @@ class InternalWeekViewPage extends StatelessWidget { decoration: BoxDecoration( border: Border( right: BorderSide( - color: hourIndicatorSettings.color, - width: hourIndicatorSettings.height, + color: widget.hourIndicatorSettings.color, + width: + widget.hourIndicatorSettings.height, ), ), ), - height: height, - width: weekTitleWidth, + height: widget.height, + width: widget.weekTitleWidth, child: Stack( children: [ PressDetector( - width: weekTitleWidth, - height: height, - heightPerMinute: heightPerMinute, - date: dates[index], - onDateTap: onDateTap, - onDateLongPress: onDateLongPress, - minuteSlotSize: minuteSlotSize, + width: widget.weekTitleWidth, + height: widget.height, + heightPerMinute: widget.heightPerMinute, + date: widget.dates[index], + onDateTap: widget.onDateTap, + onDateLongPress: widget.onDateLongPress, + minuteSlotSize: widget.minuteSlotSize, ), EventGenerator( - height: height, + height: widget.height, date: filteredDates[index], - onTileTap: onTileTap, - width: weekTitleWidth, - eventArranger: eventArranger, - eventTileBuilder: eventTileBuilder, - scrollNotifier: scrollConfiguration, - events: controller + onTileTap: widget.onTileTap, + width: widget.weekTitleWidth, + eventArranger: widget.eventArranger, + eventTileBuilder: widget.eventTileBuilder, + scrollNotifier: + widget.scrollConfiguration, + events: widget.controller .getEventsOnDay(filteredDates[index]), - heightPerMinute: heightPerMinute, + heightPerMinute: widget.heightPerMinute, ), ], ), @@ -275,11 +316,11 @@ class InternalWeekViewPage extends StatelessWidget { ), ), TimeLine( - timeLineWidth: timeLineWidth, - hourHeight: hourHeight, - height: height, - timeLineOffset: timeLineOffset, - timeLineBuilder: timeLineBuilder, + timeLineWidth: widget.timeLineWidth, + hourHeight: widget.hourHeight, + height: widget.height, + timeLineOffset: widget.timeLineOffset, + timeLineBuilder: widget.timeLineBuilder, ), ], ), @@ -294,9 +335,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 8e54049c..7c93b538 100644 --- a/lib/src/week_view/week_view.dart +++ b/lib/src/week_view/week_view.dart @@ -236,6 +236,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; @@ -265,7 +266,6 @@ class WeekViewState extends State> { EventController? _controller; - late ScrollController _scrollController; late List _weekDays; final _scrollConfiguration = EventScrollConfiguration(); @@ -273,6 +273,7 @@ class WeekViewState extends State> { @override void initState() { super.initState(); + _lastScrollOffset = widget.scrollOffset; _reloadCallback = _reload; @@ -284,8 +285,7 @@ class WeekViewState extends State> { _regulateCurrentDate(); _calculateHeights(); - _scrollController = - ScrollController(initialScrollOffset: widget.scrollOffset); + _pageController = PageController(initialPage: _currentIndex); _eventArranger = widget.eventArranger ?? SideEventArranger(); @@ -412,12 +412,13 @@ class WeekViewState extends State> { showVerticalLine: true, controller: controller, hourHeight: _hourHeight, - scrollController: _scrollController, eventArranger: _eventArranger, weekDays: _weekDays, minuteSlotSize: widget.minuteSlotSize, scrollConfiguration: _scrollConfiguration, fullDayEventBuilder: _fullDayEventBuilder, + scrollOffset: _lastScrollOffset, + scrollListener: _scrollPageListener, ), ); }, @@ -793,4 +794,9 @@ 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; + } }