diff --git a/src/view/com/pager/Pager.tsx b/src/view/com/pager/Pager.tsx index 0a22806d2e..f71bb3c1c4 100644 --- a/src/view/com/pager/Pager.tsx +++ b/src/view/com/pager/Pager.tsx @@ -76,18 +76,19 @@ export const Pager = forwardRef>( [pagerView], ) + const pendingPage = useSharedValue(selectedPage) const dragPage = useSharedValue(selectedPage) const dragProgress = useSharedValue(0) const dragState = useSharedValue<'idle' | 'settling' | 'dragging'>('idle') const handlePageScroll = usePagerHandlers( + // These events don't fire exactly the same way on Android and iOS. + // In these handlers we normalize the behavior to have consistent output values. { onPageScroll(e: PagerViewOnPageScrollEventData) { 'worklet' let {position, offset} = e - if (position === dragPage.value) { - dragProgress.set(offset) - } else { - const offsetFromPage = position + offset - dragPage.value + if (offset !== 0) { + const offsetFromPage = offset + (position - dragPage.value) dragProgress.set(offsetFromPage) } }, @@ -95,12 +96,22 @@ export const Pager = forwardRef>( 'worklet' dragState.set(e.pageScrollState) parentOnPageScrollStateChanged?.(e.pageScrollState) + if (e.pageScrollState === 'idle') { + const page = pendingPage.get() + dragPage.set(page) + dragProgress.set(0) + runOnJS(onPageSelectedJSThread)(page) + } }, onPageSelected(e: PagerViewOnPageSelectedEventData) { 'worklet' - dragPage.set(e.position) - dragProgress.set(0) - runOnJS(onPageSelectedJSThread)(e.position) + pendingPage.set(e.position) + if (dragState.value === 'idle') { + const page = e.position + dragPage.set(page) + dragProgress.set(0) + runOnJS(onPageSelectedJSThread)(e.position) + } }, }, [parentOnPageScrollStateChanged], diff --git a/src/view/com/pager/TabBar.tsx b/src/view/com/pager/TabBar.tsx index f633c658f8..a9f6a50814 100644 --- a/src/view/com/pager/TabBar.tsx +++ b/src/view/com/pager/TabBar.tsx @@ -4,7 +4,6 @@ import Animated, { scrollTo, useAnimatedReaction, useAnimatedRef, - useAnimatedStyle, useSharedValue, } from 'react-native-reanimated' @@ -47,24 +46,17 @@ export function TabBar({ const {dragPage, dragProgress} = dragGesture useAnimatedReaction( - () => dragPage.get(), - (page, prevPage) => { - if (page !== prevPage) { + () => dragPage.get() + dragProgress.get(), + (next, prev) => { + if (next !== prev) { const offsetPerPage = contentSize.get() - containerSize.get() - const offset = (dragPage.get() / (itemsLength - 1)) * offsetPerPage + const offset = (next / (itemsLength - 1)) * offsetPerPage scrollTo(scrollElRef, offset, 0, false) + return } }, ) - const contentStyle = useAnimatedStyle(() => { - const offsetPerPage = contentSize.get() - containerSize.get() - const offset = (dragProgress.get() / (itemsLength - 1)) * offsetPerPage - return { - transform: [{translateX: -offset}], - } - }) - return ( { contentSize.set(e.nativeEvent.layout.width) }} - style={[ - contentStyle, - { - flexDirection: 'row', - }, - ]}> + style={{flexDirection: 'row'}}> {items.map((item, i) => { return (