diff --git a/SampleJTAppleCalendar/Example Calendars/ViewController.swift b/SampleJTAppleCalendar/Example Calendars/ViewController.swift index a0fd41a5..0c4e7f67 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, + .stopAtFirstRowOfEachSection ] @IBAction func changeScroll(_ sender: Any) { diff --git a/Sources/JTAppleCalendar/CalendarEnums.swift b/Sources/JTAppleCalendar/CalendarEnums.swift index 652e25b3..9fa53087 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 + /// 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 59fde969..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: 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 ec2d7290..ca2c4fa1 100644 --- a/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift +++ b/Sources/JTAppleCalendar/JTACScrollViewDelegates.swift @@ -106,6 +106,52 @@ 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 .stopAtFirstRowOfEachSection: + 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 { + 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] ?? defaultValue + } + + 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] + monthHeaderSize(for: theCurrentSection) + + 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: {