From 0bad792f70a5372870dcfb14e0007ffa364c3d59 Mon Sep 17 00:00:00 2001 From: Igor B Date: Mon, 20 Apr 2020 23:05:51 +0100 Subject: [PATCH 1/4] add stopAtEachFirstRowOfSection ScrollingMode --- .../Example Calendars/ViewController.swift | 3 +- Sources/JTAppleCalendar/CalendarEnums.swift | 2 + Sources/JTAppleCalendar/JTACMonthView.swift | 2 +- .../JTACScrollViewDelegates.swift | 43 +++++++++++++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/SampleJTAppleCalendar/Example Calendars/ViewController.swift b/SampleJTAppleCalendar/Example Calendars/ViewController.swift index a0fd41a5..de7b1eb0 100644 --- a/SampleJTAppleCalendar/Example Calendars/ViewController.swift +++ b/SampleJTAppleCalendar/Example Calendars/ViewController.swift @@ -40,7 +40,8 @@ class ViewController: UIViewController { .nonStopToSection(withResistance: 0.5), .stopAtEach(customInterval: 374), .stopAtEachCalendarFrame, - .stopAtEachSection + .stopAtEachSection, + .stopAtEachFirstRowOfSection ] @IBAction func changeScroll(_ sender: Any) { diff --git a/Sources/JTAppleCalendar/CalendarEnums.swift b/Sources/JTAppleCalendar/CalendarEnums.swift index 652e25b3..c9159764 100644 --- a/Sources/JTAppleCalendar/CalendarEnums.swift +++ b/Sources/JTAppleCalendar/CalendarEnums.swift @@ -66,6 +66,8 @@ public enum ScrollingMode: Equatable { case stopAtEachCalendarFrame /// stopAtEachSection - non-continuous scrolling that will stop at each section case stopAtEachSection + /// stopAtEachFirstRowOfSection - non-continous scrolling that will stop at first row of each section + case stopAtEachFirstRowOfSection /// stopAtEach - non-continuous scrolling that will stop at each custom interval case stopAtEach(customInterval: CGFloat) /// nonStopToSection - continuous scrolling that will stop at a section diff --git a/Sources/JTAppleCalendar/JTACMonthView.swift b/Sources/JTAppleCalendar/JTACMonthView.swift index 59fde969..7a72c7ab 100644 --- a/Sources/JTAppleCalendar/JTACMonthView.swift +++ b/Sources/JTAppleCalendar/JTACMonthView.swift @@ -198,7 +198,7 @@ open class JTACMonthView: UICollectionView { var decelerationRateMatchingScrollingMode: CGFloat { switch scrollingMode { case .stopAtEachCalendarFrame: return UIScrollView.DecelerationRate.fast.rawValue - case .stopAtEach, .stopAtEachSection: return UIScrollView.DecelerationRate.fast.rawValue + case .stopAtEach, .stopAtEachSection, .stopAtEachFirstRowOfSection: return UIScrollView.DecelerationRate.fast.rawValue case .nonStopToSection, .nonStopToCell, .nonStopTo, .none: return UIScrollView.DecelerationRate.normal.rawValue } } diff --git a/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift index ec2d7290..b937d3c7 100644 --- a/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift +++ b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift @@ -106,6 +106,49 @@ extension JTACMonthView: UIScrollViewDelegate { let snapForward = midPoint - ((maxSnap - midPoint) * modifiedPercentage) + scrollDecision(currentScrollDirectionValue: translation, + previousScrollDirectionValue: lastMovedScrollDirection, + forward: { + if theCurrentContentOffset >= snapForward || directionVelocity > 0 { + setTargetContentOffset(endOfCurrentSectionOffset) + } else { + setTargetContentOffset(endOfPreviousSectionOffset) + } + }, + backward: { + if theCurrentContentOffset <= snapForward || directionVelocity < 0 { + setTargetContentOffset(endOfPreviousSectionOffset) + } else { + setTargetContentOffset(endOfCurrentSectionOffset) + } + }) + case .stopAtEachFirstRowOfSection: + let section = scrollDecision(currentScrollDirectionValue: translation, + previousScrollDirectionValue: lastMovedScrollDirection, + forward: { return theCurrentSection}, + backward: { return theCurrentSection - 1}, + fixed: { return theCurrentSection}) + + guard section >= 0, section < calendarLayout.endOfSectionOffsets.count else {setTargetContentOffset(0); return} + + func monthHeaderSize(for section: Int) -> CGFloat { + guard let monthOfYear = self.monthInfoFromSection(section)?.month, + let month = MonthsOfYear(rawValue: monthOfYear) else { return 0 } + + return self.lastMonthSize[month] ?? self.lastMonthSize["default"] ?? 0 + } + + let endOfCurrentSectionOffset = calendarLayout.endOfSectionOffsets[theCurrentSection] + monthHeaderSize(for: theCurrentSection) + let previousSection = theCurrentSection - 1 < 0 ? 0 : theCurrentSection - 1 + let endOfPreviousSectionOffset = calendarLayout.endOfSectionOffsets[previousSection] + monthHeaderSize(for: previousSection) + let midPoint = (endOfCurrentSectionOffset + endOfPreviousSectionOffset) / 2 + let maxSnap = calendarLayout.endOfSectionOffsets[section] + + let userPercentage: CGFloat = 20 + let modifiedPercentage = CGFloat((100 - userPercentage) / 100.0) + + let snapForward = midPoint - ((maxSnap - midPoint) * modifiedPercentage) + scrollDecision(currentScrollDirectionValue: translation, previousScrollDirectionValue: lastMovedScrollDirection, forward: { From 5111a4852e0f41644aca261d994a5f3398dd4dea Mon Sep 17 00:00:00 2001 From: Igor B Date: Mon, 20 Apr 2020 23:17:03 +0100 Subject: [PATCH 2/4] rename to stopAtFirstRowOfEachSection - broken english --- SampleJTAppleCalendar/Example Calendars/ViewController.swift | 2 +- Sources/JTAppleCalendar/CalendarEnums.swift | 4 ++-- Sources/JTAppleCalendar/JTACMonthView.swift | 2 +- Sources/JTAppleCalendar/JTACScrollViewDelegates.swift | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SampleJTAppleCalendar/Example Calendars/ViewController.swift b/SampleJTAppleCalendar/Example Calendars/ViewController.swift index de7b1eb0..0c4e7f67 100644 --- a/SampleJTAppleCalendar/Example Calendars/ViewController.swift +++ b/SampleJTAppleCalendar/Example Calendars/ViewController.swift @@ -41,7 +41,7 @@ class ViewController: UIViewController { .stopAtEach(customInterval: 374), .stopAtEachCalendarFrame, .stopAtEachSection, - .stopAtEachFirstRowOfSection + .stopAtFirstRowOfEachSection ] @IBAction func changeScroll(_ sender: Any) { diff --git a/Sources/JTAppleCalendar/CalendarEnums.swift b/Sources/JTAppleCalendar/CalendarEnums.swift index c9159764..9fa53087 100644 --- a/Sources/JTAppleCalendar/CalendarEnums.swift +++ b/Sources/JTAppleCalendar/CalendarEnums.swift @@ -66,8 +66,8 @@ public enum ScrollingMode: Equatable { case stopAtEachCalendarFrame /// stopAtEachSection - non-continuous scrolling that will stop at each section case stopAtEachSection - /// stopAtEachFirstRowOfSection - non-continous scrolling that will stop at first row of each section - case stopAtEachFirstRowOfSection + /// stopAtFirstRowOfEachSection - non-continous scrolling that will stop at first row of each section + case stopAtFirstRowOfEachSection /// stopAtEach - non-continuous scrolling that will stop at each custom interval case stopAtEach(customInterval: CGFloat) /// nonStopToSection - continuous scrolling that will stop at a section diff --git a/Sources/JTAppleCalendar/JTACMonthView.swift b/Sources/JTAppleCalendar/JTACMonthView.swift index 7a72c7ab..1c4e3e81 100644 --- a/Sources/JTAppleCalendar/JTACMonthView.swift +++ b/Sources/JTAppleCalendar/JTACMonthView.swift @@ -198,7 +198,7 @@ open class JTACMonthView: UICollectionView { var decelerationRateMatchingScrollingMode: CGFloat { switch scrollingMode { case .stopAtEachCalendarFrame: return UIScrollView.DecelerationRate.fast.rawValue - case .stopAtEach, .stopAtEachSection, .stopAtEachFirstRowOfSection: return UIScrollView.DecelerationRate.fast.rawValue + case .stopAtEach, .stopAtEachSection, .stopAtFirstRowOfEachSection: return UIScrollView.DecelerationRate.fast.rawValue case .nonStopToSection, .nonStopToCell, .nonStopTo, .none: return UIScrollView.DecelerationRate.normal.rawValue } } diff --git a/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift index b937d3c7..72b5d3e9 100644 --- a/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift +++ b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift @@ -122,7 +122,7 @@ extension JTACMonthView: UIScrollViewDelegate { setTargetContentOffset(endOfCurrentSectionOffset) } }) - case .stopAtEachFirstRowOfSection: + case .stopAtFirstRowOfEachSection: let section = scrollDecision(currentScrollDirectionValue: translation, previousScrollDirectionValue: lastMovedScrollDirection, forward: { return theCurrentSection}, From 21c13c0eda48c6974c7251d71958dcb9dd3c0e6e Mon Sep 17 00:00:00 2001 From: Igor B Date: Tue, 21 Apr 2020 23:43:58 +0100 Subject: [PATCH 3/4] fix targetOffset algorithm --- .../JTAppleCalendar/JTACScrollViewDelegates.swift | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift index 72b5d3e9..885128c2 100644 --- a/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift +++ b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift @@ -132,15 +132,18 @@ extension JTACMonthView: UIScrollViewDelegate { guard section >= 0, section < calendarLayout.endOfSectionOffsets.count else {setTargetContentOffset(0); return} func monthHeaderSize(for section: Int) -> CGFloat { - guard let monthOfYear = self.monthInfoFromSection(section)?.month, - let month = MonthsOfYear(rawValue: monthOfYear) else { return 0 } + let defaultValue = self.lastMonthSize["default"] ?? 0 + guard let monthNumber = self.monthInfoFromSection(section)?.month, + let month = MonthsOfYear(rawValue: monthNumber - 1) else { return defaultValue } - return self.lastMonthSize[month] ?? self.lastMonthSize["default"] ?? 0 + return self.lastMonthSize[month] ?? defaultValue } - let endOfCurrentSectionOffset = calendarLayout.endOfSectionOffsets[theCurrentSection] + monthHeaderSize(for: theCurrentSection) let previousSection = theCurrentSection - 1 < 0 ? 0 : theCurrentSection - 1 - let endOfPreviousSectionOffset = calendarLayout.endOfSectionOffsets[previousSection] + monthHeaderSize(for: previousSection) + let nextSection = section == self.numberOfSections - 1 ? section : section + 1 + let endOfCurrentSectionOffset = calendarLayout.endOfSectionOffsets[theCurrentSection] + monthHeaderSize(for: nextSection) + let endOfPreviousSectionOffset = calendarLayout.endOfSectionOffsets[previousSection] + let midPoint = (endOfCurrentSectionOffset + endOfPreviousSectionOffset) / 2 let maxSnap = calendarLayout.endOfSectionOffsets[section] From b19aa22560819befad241273add2c0a9b24af5fc Mon Sep 17 00:00:00 2001 From: Igor B Date: Tue, 21 Apr 2020 23:49:07 +0100 Subject: [PATCH 4/4] still fixing --- Sources/JTAppleCalendar/JTACScrollViewDelegates.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift index 885128c2..ca2c4fa1 100644 --- a/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift +++ b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift @@ -142,7 +142,7 @@ extension JTACMonthView: UIScrollViewDelegate { let previousSection = theCurrentSection - 1 < 0 ? 0 : theCurrentSection - 1 let nextSection = section == self.numberOfSections - 1 ? section : section + 1 let endOfCurrentSectionOffset = calendarLayout.endOfSectionOffsets[theCurrentSection] + monthHeaderSize(for: nextSection) - let endOfPreviousSectionOffset = calendarLayout.endOfSectionOffsets[previousSection] + let endOfPreviousSectionOffset = calendarLayout.endOfSectionOffsets[previousSection] + monthHeaderSize(for: theCurrentSection) let midPoint = (endOfCurrentSectionOffset + endOfPreviousSectionOffset) / 2 let maxSnap = calendarLayout.endOfSectionOffsets[section]