Skip to content

Commit 2318146

Browse files
authored
fix: emit onPageScroll with zero offset on idle to prevent indicator jump (#1076)
1 parent dff04db commit 2318146

2 files changed

Lines changed: 28 additions & 5 deletions

File tree

android/src/main/java/com/reactnativepagerview/PagerViewViewManager.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ class PagerViewViewManager : ViewGroupManager<NestedScrollableHost>(), RNCViewPa
7575
ViewPager2.SCROLL_STATE_SETTLING -> "settling"
7676
else -> throw IllegalStateException("Unsupported pageScrollState")
7777
}
78+
// Emit a final onPageScroll with offset 0 when idle to clear
79+
// any residual floating-point offset from the scroll animation
80+
if (state == ViewPager2.SCROLL_STATE_IDLE) {
81+
UIManagerHelper.getEventDispatcherForReactTag(reactContext, host.id)?.dispatchEvent(
82+
PageScrollEvent(host.id, vp.currentItem, 0f)
83+
)
84+
}
7885
UIManagerHelper.getEventDispatcherForReactTag(reactContext, host.id)?.dispatchEvent(
7986
PageScrollStateChangedEvent(host.id, pageScrollState)
8087
)

ios/PagerScrollDelegate.swift

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,22 @@ class PagerScrollDelegate: NSObject, UIScrollViewDelegate, UICollectionViewDeleg
3333
delegate?.onPageScroll(data: eventData)
3434
originalDelegate?.scrollViewDidScroll?(scrollView)
3535
}
36+
37+
/// Emits a final onPageScroll with offset 0 before transitioning to idle,
38+
/// clearing any residual floating-point offset from the scroll animation.
39+
private func emitIdleWithCleanOffset(_ scrollView: UIScrollView) {
40+
let isHorizontal = orientation == .horizontal
41+
let pageSize = isHorizontal ? scrollView.frame.width : scrollView.frame.height
42+
let contentOffset = isHorizontal ? scrollView.contentOffset.x : scrollView.contentOffset.y
43+
44+
if pageSize > 0 {
45+
let page = Int(round(contentOffset / pageSize))
46+
let eventData = OnPageScrollEventData(position: Double(page), offset: 0)
47+
delegate?.onPageScroll(data: eventData)
48+
}
49+
50+
delegate?.onPageScrollStateChanged(state: .idle)
51+
}
3652

3753
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
3854
delegate?.onPageScrollStateChanged(state: .dragging)
@@ -45,18 +61,18 @@ class PagerScrollDelegate: NSObject, UIScrollViewDelegate, UICollectionViewDeleg
4561
}
4662

4763
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
48-
delegate?.onPageScrollStateChanged(state: .idle)
64+
emitIdleWithCleanOffset(scrollView)
4965
originalDelegate?.scrollViewDidEndDecelerating?(scrollView)
5066
}
51-
67+
5268
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
53-
delegate?.onPageScrollStateChanged(state: .idle)
69+
emitIdleWithCleanOffset(scrollView)
5470
originalDelegate?.scrollViewDidEndScrollingAnimation?(scrollView)
5571
}
56-
72+
5773
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
5874
if !decelerate {
59-
delegate?.onPageScrollStateChanged(state: .idle)
75+
emitIdleWithCleanOffset(scrollView)
6076
}
6177
originalDelegate?.scrollViewDidEndDragging?(scrollView, willDecelerate: decelerate)
6278
}

0 commit comments

Comments
 (0)