You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:12:44