From f0bf686893117990891fad98cba4c9fb0e544f8d Mon Sep 17 00:00:00 2001 From: yinminqian Date: Fri, 8 May 2026 15:24:46 +0800 Subject: [PATCH] feat: expose `disableIntervalMomentum` as opt-in Picker prop Adds an optional `disableIntervalMomentum` prop to ``, threaded through to both the regular `List` (Animated.ScrollView) and the virtualized list (Animated.FlatList). Both already use `snapToOffsets`, so the prop applies on either path. Defaults to React Native's default (off), so existing UX is unchanged. Affected Android devices (vivo / Oppo, see #74 and facebook/react-native#29922) can opt in via `disableIntervalMomentum={true}` to avoid erratic snap behavior, without changing the default for everyone else. --- README.md | 1 + src/base/list/List.tsx | 3 +++ src/base/picker/Picker.tsx | 1 + src/hoc/virtualized/VirtualizedList.tsx | 4 ++++ 4 files changed, 9 insertions(+) diff --git a/README.md b/README.md index af5f888..135036b 100644 --- a/README.md +++ b/README.md @@ -285,6 +285,7 @@ const App = () => { - ```overlayItemStyle?``` [object | array] - style for the overlay element in the center - ```contentContainerStyle?``` [object | array] - style which wraps all of the child views [original](https://reactnative.dev/docs/scrollview#contentcontainerstyle) - ```scrollEventThrottle?``` [object | array] - [original](https://reactnative.dev/docs/scrollview#scrolleventthrottle-ios) +- ```disableIntervalMomentum?``` [boolean] - When set to `true`, the scroll view stops on the next snap point relative to the release position instead of carrying through with momentum. Useful as an opt-in workaround for a [react-native bug](https://github.com/facebook/react-native/issues/29922) where some older Android OEM devices (e.g. vivo / Oppo) produce erratic snap behavior. Defaults to React Native's default (off). #### usePickerItemHeight diff --git a/src/base/list/List.tsx b/src/base/list/List.tsx index 5c35cdc..d68017c 100644 --- a/src/base/list/List.tsx +++ b/src/base/list/List.tsx @@ -42,6 +42,7 @@ export type ListProps> = { onScrollStart: (() => void) | undefined; onScrollEnd: () => void; contentContainerStyle: StyleProp | undefined; + disableIntervalMomentum?: boolean; }; const List = >( @@ -60,6 +61,7 @@ const List = >( onScrollStart, onScrollEnd, contentContainerStyle: contentContainerStyleProp, + disableIntervalMomentum, ...restProps }: ListProps, forwardedRef: ForwardedRef, @@ -116,6 +118,7 @@ const List = >( onScroll={onScroll} scrollOffset={scrollOffset} snapToOffsets={snapToOffsets} + disableIntervalMomentum={disableIntervalMomentum} style={styles.list} contentContainerStyle={contentContainerStyle} onTouchStart={onTouchStart} diff --git a/src/base/picker/Picker.tsx b/src/base/picker/Picker.tsx index 5f25f05..2cbe8fc 100644 --- a/src/base/picker/Picker.tsx +++ b/src/base/picker/Picker.tsx @@ -58,6 +58,7 @@ export type PickerProps> = { contentContainerStyle?: StyleProp; scrollEventThrottle?: number; + disableIntervalMomentum?: boolean; _enableSyncScrollAfterScrollEnd?: boolean; _onScrollStart?: () => void; diff --git a/src/hoc/virtualized/VirtualizedList.tsx b/src/hoc/virtualized/VirtualizedList.tsx index 4248e0d..177afcb 100644 --- a/src/hoc/virtualized/VirtualizedList.tsx +++ b/src/hoc/virtualized/VirtualizedList.tsx @@ -49,6 +49,7 @@ type VirtualizedListProps> = { onScrollStart: (() => void) | undefined; onScrollEnd: () => void; contentContainerStyle: StyleProp | undefined; + disableIntervalMomentum?: boolean; } & AdditionalProps; const VirtualizedList = >( @@ -74,6 +75,8 @@ const VirtualizedList = >( updateCellsBatchingPeriod = 10, windowSize, + disableIntervalMomentum, + ...restProps }: VirtualizedListProps, forwardedRef: ForwardedRef, @@ -123,6 +126,7 @@ const VirtualizedList = >( onScroll={onScroll} scrollOffset={scrollOffset} snapToOffsets={snapToOffsets} + disableIntervalMomentum={disableIntervalMomentum} style={styles.list} contentContainerStyle={contentContainerStyle} onTouchStart={onTouchStart}