React Native中如何用Animated.event获取滚动偏移Y值?useNativeDriver:true返回0
React Native 使用 Animated.event 配合 useNativeDriver: true 无法获取正确滚动偏移Y值
问题场景
在React Native中尝试通过Animated.event获取FlatList的滚动偏移Y值,当设置useNativeDriver: false时可以正常获取到正确的偏移数值,但将其改为useNativeDriver: true后,输出的偏移值始终为0,需要保留useNativeDriver: true的设置来优化性能。
问题原因
当启用useNativeDriver: true时,Animated的值会在原生线程中运行,JavaScript线程无法直接访问_value属性(这是React Native内部实现的非公开属性)——原生线程的数值不会同步到JS线程的这个属性上,所以你拿到的始终是初始值0。
解决方案
方案一:通过监听器同步值到JS变量
给Animated.Value添加监听器,在值更新时同步到一个JS状态变量中,确保能获取到最新的偏移值:
import React, {useRef, useState, useEffect} from 'react'; import { SafeAreaView, View, StyleSheet, Text, StatusBar, Button, Animated } from 'react-native'; const DATA = [{id: 0},{id: 1},{id: 2},{id: 3},{id: 4},{id: 5},{id: 6},{id: 7},{id: 8},{id: 9}]; const Item = ({title}) => ( <View style={styles.item}> <Text style={styles.title}>{title}</Text> </View> ); const App = () => { const contentOffsetY = useRef(new Animated.Value(0)).current; const [scrollY, setScrollY] = useState(0); // 添加监听器同步原生线程的值到JS变量 useEffect(() => { const listener = contentOffsetY.addListener(({ value }) => { setScrollY(value); }); // 组件卸载时移除监听器 return () => contentOffsetY.removeListener(listener); }, []); const onScroll = Animated.event( [{ nativeEvent: { contentOffset: { y: contentOffsetY } } }], { useNativeDriver: true } ); function getY(){ console.log(scrollY); } return ( <SafeAreaView style={styles.container}> <Button title="get Y" onPress={getY}/> <Animated.FlatList onScroll={onScroll} scrollEventThrottle={16} // 可选:确保事件触发频率足够 data={DATA} renderItem={({item}) => <Item title={item.id} />} keyExtractor={item => item.id} /> </SafeAreaView> ); }; const styles = StyleSheet.create({ container: { flex: 1, marginTop: StatusBar.currentHeight || 0, }, item: { backgroundColor: '#f9c2ff', padding: 20, marginVertical: 8, marginHorizontal: 16, }, title: { fontSize: 32, }, }); export default App;
方案二:使用Animated.getValue()异步获取(React Native 0.60+)
如果只是偶尔需要获取当前偏移值,可以用getValue()方法异步获取原生线程中的最新值,该方法返回Promise:
// 修改原代码中的getY函数 async function getY(){ const currentY = await contentOffsetY.getValue(); console.log(currentY); }
注意事项
- 禁止直接访问
_value属性,这是React Native内部实现细节,未来可能被移除,不属于官方公开API。 - 启用
useNativeDriver后,所有和该Animated.Value相关的动画操作都应使用原生驱动,避免混合线程操作导致的异常。
内容的提问来源于stack exchange,提问作者Blogger Klik
相关产品推荐
相关产品推荐

