 extension PageboyViewController: UIScrollViewDelegate {
     
     public func scrollViewDidScroll(_ scrollView: UIScrollView) {
-        guard scrollViewIsActual(scrollView) else {
+        guard let currentIndex = self.currentIndex, scrollViewIsActual(scrollView) else {
             return
         }
         guard updateContentOffsetForBounceIfNeeded(scrollView: scrollView) == false else {
             return
         }
         
-        guard let currentIndex = self.currentIndex else {
-            return
-        }
-        
-        let previousPagePosition = self.previousPagePosition ?? 0.0
-        let (pageSize, contentOffset) = calculateRelativePageSizeAndContentOffset(for: scrollView)
-        
-        guard let scrollIndexDiff = self.pageScrollIndexDiff(forCurrentIndex: currentIndex,
-                                                             expectedIndex: self.expectedTransitionIndex,
-                                                             currentContentOffset: contentOffset,
-                                                             pageSize: pageSize) else {
-                                                                return
-        }
-        guard var pagePosition = calculatePagePosition(for: contentOffset,
-                                               pageSize: pageSize,
-                                               indexDiff: scrollIndexDiff) else {
-                                                return
-        }
-        
+        guard let (newPosition, previousPosition) = calculateNewPagePosition(in: scrollView, currentIndex: currentIndex) else {
+            return
+        }
         // do not continue if a page change is detected
-        let didDetectNewPage = detectNewPageIndexIfNeeded(pagePosition: pagePosition,
+        let didDetectNewPage = detectNewPageIndexIfNeeded(pagePosition: newPosition,
                                                           scrollView: scrollView)
         guard !didDetectNewPage else {
             return
         }
         
-        // do not continue if previous position equals current
-        if previousPagePosition == pagePosition {
-            return
-        }
-        
-        // update relative page position for infinite overscroll if required
-        detectInfiniteOverscrollIfNeeded(pagePosition: &pagePosition)
+        // update page position for infinite overscroll if required
+        let pagePosition: CGFloat
+        if let infiniteAdjustedPosition = adjustedPagePositionForInfiniteOverscroll(from: newPosition) {
+            pagePosition = infiniteAdjustedPosition
+        } else {
+            pagePosition = newPosition
+        }
         
         // provide scroll updates
         var positionPoint: CGPoint!
-        let direction = NavigationDirection.forPosition(pagePosition, previous: previousPagePosition)
+        let direction = NavigationDirection.forPosition(pagePosition, previous: previousPosition)
         if self.navigationOrientation == .horizontal {
             positionPoint = CGPoint(x: pagePosition, y: scrollView.contentOffset.y)
         } else {

            infinitePagePosition = maxInfinitePosition
        }
        
        pagePosition = infinitePagePosition
    }
    
    /// Whether a position is infinitely scrolling between end ranges

    }
    
    /// Detect whether the scroll view is overscrolling while infinite scroll is enabled
    ///
    /// - Parameter pagePosition: the current page position.
    /// - Returns: The updated page position (if needed).
    private func adjustedPagePositionForInfiniteOverscroll(from pagePosition: CGFloat) -> CGFloat? {
        guard self.isInfinitelyScrolling(forPosition: pagePosition) else {
            return nil
        }
        
        let maxPagePosition = CGFloat((self.viewControllerCount ?? 1) - 1)
