From a1362a7dfdf160f33951c215c796f6022bf903d5 Mon Sep 17 00:00:00 2001 From: MrRefactor Date: Sat, 11 Apr 2026 00:03:40 +0200 Subject: [PATCH] fix: emit onPageScroll with zero offset on idle to prevent indicator jump --- .../PagerViewViewManager.kt | 7 +++++ ios/PagerScrollDelegate.swift | 26 +++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/android/src/main/java/com/reactnativepagerview/PagerViewViewManager.kt b/android/src/main/java/com/reactnativepagerview/PagerViewViewManager.kt index 8ec286a7..7089af09 100644 --- a/android/src/main/java/com/reactnativepagerview/PagerViewViewManager.kt +++ b/android/src/main/java/com/reactnativepagerview/PagerViewViewManager.kt @@ -75,6 +75,13 @@ class PagerViewViewManager : ViewGroupManager(), RNCViewPa ViewPager2.SCROLL_STATE_SETTLING -> "settling" else -> throw IllegalStateException("Unsupported pageScrollState") } + // Emit a final onPageScroll with offset 0 when idle to clear + // any residual floating-point offset from the scroll animation + if (state == ViewPager2.SCROLL_STATE_IDLE) { + UIManagerHelper.getEventDispatcherForReactTag(reactContext, host.id)?.dispatchEvent( + PageScrollEvent(host.id, vp.currentItem, 0f) + ) + } UIManagerHelper.getEventDispatcherForReactTag(reactContext, host.id)?.dispatchEvent( PageScrollStateChangedEvent(host.id, pageScrollState) ) diff --git a/ios/PagerScrollDelegate.swift b/ios/PagerScrollDelegate.swift index 962ee7b8..5b09e032 100644 --- a/ios/PagerScrollDelegate.swift +++ b/ios/PagerScrollDelegate.swift @@ -33,6 +33,22 @@ class PagerScrollDelegate: NSObject, UIScrollViewDelegate, UICollectionViewDeleg delegate?.onPageScroll(data: eventData) originalDelegate?.scrollViewDidScroll?(scrollView) } + + /// Emits a final onPageScroll with offset 0 before transitioning to idle, + /// clearing any residual floating-point offset from the scroll animation. + private func emitIdleWithCleanOffset(_ scrollView: UIScrollView) { + let isHorizontal = orientation == .horizontal + let pageSize = isHorizontal ? scrollView.frame.width : scrollView.frame.height + let contentOffset = isHorizontal ? scrollView.contentOffset.x : scrollView.contentOffset.y + + if pageSize > 0 { + let page = Int(round(contentOffset / pageSize)) + let eventData = OnPageScrollEventData(position: Double(page), offset: 0) + delegate?.onPageScroll(data: eventData) + } + + delegate?.onPageScrollStateChanged(state: .idle) + } func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { delegate?.onPageScrollStateChanged(state: .dragging) @@ -45,18 +61,18 @@ class PagerScrollDelegate: NSObject, UIScrollViewDelegate, UICollectionViewDeleg } func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { - delegate?.onPageScrollStateChanged(state: .idle) + emitIdleWithCleanOffset(scrollView) originalDelegate?.scrollViewDidEndDecelerating?(scrollView) } - + func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { - delegate?.onPageScrollStateChanged(state: .idle) + emitIdleWithCleanOffset(scrollView) originalDelegate?.scrollViewDidEndScrollingAnimation?(scrollView) } - + func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { if !decelerate { - delegate?.onPageScrollStateChanged(state: .idle) + emitIdleWithCleanOffset(scrollView) } originalDelegate?.scrollViewDidEndDragging?(scrollView, willDecelerate: decelerate) }