Simplify the implementation
I was trying to be too smart and this was causing the current page event to lag behind if you continuously drag. Better to let the library do its job.
This commit is contained in:
@@ -76,23 +76,13 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
||||
[pagerView],
|
||||
)
|
||||
|
||||
const pendingPage = useSharedValue(selectedPage)
|
||||
const dragPage = useSharedValue(selectedPage)
|
||||
const dragProgress = useSharedValue(0)
|
||||
const dragState = useSharedValue<'idle' | 'settling' | 'dragging'>('idle')
|
||||
const dragProgress = useSharedValue(selectedPage)
|
||||
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 (offset !== 0) {
|
||||
// Normalize so that we always track the offset according to the
|
||||
// last settled page from the application point of view.
|
||||
const offsetFromPage = offset + (position - dragPage.value)
|
||||
dragProgress.set(offsetFromPage)
|
||||
}
|
||||
dragProgress.set(e.offset + e.position)
|
||||
},
|
||||
onPageScrollStateChanged(e: PageScrollStateChangedNativeEventData) {
|
||||
'worklet'
|
||||
@@ -103,27 +93,10 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
||||
}
|
||||
dragState.set(e.pageScrollState)
|
||||
parentOnPageScrollStateChanged?.(e.pageScrollState)
|
||||
if (e.pageScrollState === 'idle') {
|
||||
// This is a good time to update the last known settled page.
|
||||
const page = pendingPage.get()
|
||||
dragPage.set(page)
|
||||
dragProgress.set(0)
|
||||
runOnJS(onPageSelectedJSThread)(page)
|
||||
}
|
||||
},
|
||||
onPageSelected(e: PagerViewOnPageSelectedEventData) {
|
||||
'worklet'
|
||||
// We don't usually emit the "page selected" event here because it fires
|
||||
// prematurely on Android. We'll emit it in the idle state handler above.
|
||||
pendingPage.set(e.position)
|
||||
if (dragState.value === 'idle') {
|
||||
// However, if we already *are* idle, this event is caused by the initial state.
|
||||
// Let's fire it here since there will be no scroll state change event later.
|
||||
const page = e.position
|
||||
dragPage.set(page)
|
||||
dragProgress.set(0)
|
||||
runOnJS(onPageSelectedJSThread)(e.position)
|
||||
}
|
||||
runOnJS(onPageSelectedJSThread)(e.position)
|
||||
},
|
||||
},
|
||||
[parentOnPageScrollStateChanged],
|
||||
@@ -135,7 +108,6 @@ export const Pager = forwardRef<PagerRef, React.PropsWithChildren<Props>>(
|
||||
selectedPage,
|
||||
onSelect: onTabBarSelect,
|
||||
dragGesture: {
|
||||
dragPage,
|
||||
dragProgress,
|
||||
dragState,
|
||||
},
|
||||
|
||||
@@ -35,20 +35,20 @@ export function TabBar({
|
||||
const containerSize = useSharedValue(0)
|
||||
const scrollX = useSharedValue(0)
|
||||
const itemsLength = items.length
|
||||
const {dragPage, dragProgress, dragState} = dragGesture
|
||||
const {dragProgress, dragState} = dragGesture
|
||||
|
||||
// When you swipe the pager, the tabbar should scroll automatically
|
||||
// as you're dragging the page and then even during deceleration.
|
||||
useAnimatedReaction(
|
||||
() => dragPage.get() + dragProgress.get(),
|
||||
(nextValue, prevValue) => {
|
||||
() => dragProgress.get(),
|
||||
(nextProgress, prevProgress) => {
|
||||
if (
|
||||
nextValue !== prevValue &&
|
||||
nextProgress !== prevProgress &&
|
||||
dragState.value !== 'idle' &&
|
||||
isSyncingScroll.get() === true
|
||||
) {
|
||||
const offsetPerPage = contentSize.get() - containerSize.get()
|
||||
const offset = (nextValue / (itemsLength - 1)) * offsetPerPage
|
||||
const offset = (nextProgress / (itemsLength - 1)) * offsetPerPage
|
||||
scrollTo(scrollElRef, offset, 0, false)
|
||||
return
|
||||
}
|
||||
@@ -69,8 +69,8 @@ export function TabBar({
|
||||
isSyncingScroll.get() === false
|
||||
) {
|
||||
const offsetPerPage = contentSize.get() - containerSize.get()
|
||||
const value = dragPage.get() + dragProgress.get()
|
||||
const offset = (value / (itemsLength - 1)) * offsetPerPage
|
||||
const progress = dragProgress.get()
|
||||
const offset = (progress / (itemsLength - 1)) * offsetPerPage
|
||||
scrollTo(scrollElRef, offset, 0, true)
|
||||
isSyncingScroll.set(true)
|
||||
}
|
||||
@@ -84,8 +84,8 @@ export function TabBar({
|
||||
'worklet'
|
||||
if (isSyncingScroll.get() === true) {
|
||||
const offsetPerPage = contentSize.get() - containerSize.get()
|
||||
const valueDiff = index - dragPage.get()
|
||||
const offsetDiff = (valueDiff / (itemsLength - 1)) * offsetPerPage
|
||||
const progressDiff = index - dragProgress.get()
|
||||
const offsetDiff = (progressDiff / (itemsLength - 1)) * offsetPerPage
|
||||
const offset = scrollX.get() + offsetDiff
|
||||
scrollTo(scrollElRef, offset, 0, true)
|
||||
}
|
||||
@@ -98,7 +98,7 @@ export function TabBar({
|
||||
itemsLength,
|
||||
scrollElRef,
|
||||
scrollX,
|
||||
dragPage,
|
||||
dragProgress,
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user