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

React Native开启useNativeDriver时,如何实时记录Animated ScrollView的contentOffset.y值更新?

Hey there! Let's work through how to get the updated scroll Y value from your Animated ScrollView when using useNativeDriver: true—I'll walk you through a few solid solutions, plus explain why your initial attempts didn't work.


Solution 1: Fix the Animated.Value.addListener Approach (Class Components)

Your initial code was on the right track, but you were accessing the wrong value and not handling the listener properly. When useNativeDriver: true, the Animated.Value's internal _value property (which you tried to print) doesn't update on the JS thread (since animations run natively). Instead, use the value passed to your listener callback, and make sure to clean up the listener to avoid memory leaks.

Here's the corrected code:

class YourScrollComponent extends React.Component {
  state = { y: new Animated.Value(0) };
  _scrollListener = null;
  _currentScrollY = 0;

  componentDidMount() {
    // Save the listener subscription so we can remove it later
    this._scrollListener = this.state.y.addListener(({ value }) => {
      this._currentScrollY = value;
      console.log("Updated scroll Y:", value); // Print immediately when the value changes
    });
  }

  componentWillUnmount() {
    // Clean up the listener when the component unmounts
    if (this._scrollListener) {
      this.state.y.removeListener(this._scrollListener);
    }
  }

  render() {
    // If you need to use the value elsewhere in your component, use this._currentScrollY
    return (
      <Animated.ScrollView
        scrollEventThrottle={16}
        showsVerticalScrollIndicator={false}
        onScroll={Animated.event(
          [{ nativeEvent: { contentOffset: { y: this.state.y } } }],
          { useNativeDriver: true }
        )}
      >
        {/* Your scrollable content goes here */}
      </Animated.ScrollView>
    );
  }
}

Solution 2: Add a Listener Directly to Animated.event

This is a more concise approach—you can attach a listener function directly in the options object of Animated.event, which fires every time the scroll event triggers (even with useNativeDriver: true).

Code example:

class YourScrollComponent extends React.Component {
  state = { y: new Animated.Value(0) };

  _onScrollUpdate = (event) => {
    const scrollY = event.nativeEvent.contentOffset.y;
    console.log("Scroll Y value:", scrollY);
    // If you need to sync this value to other parts of your app, you can update state here too
    // this.setState({ currentScrollY: scrollY });
  };

  render() {
    return (
      <Animated.ScrollView
        scrollEventThrottle={16}
        showsVerticalScrollIndicator={false}
        onScroll={Animated.event(
          [{ nativeEvent: { contentOffset: { y: this.state.y } } }],
          {
            useNativeDriver: true,
            listener: this._onScrollUpdate, // Attach your listener here
          }
        )}
      >
        {/* Your scrollable content goes here */}
      </Animated.ScrollView>
    );
  }
}

Solution 3: Functional Component Alternative (with Reanimated)

If you ever switch to functional components, using React Native Reanimated v2+ gives you a more efficient way to handle scroll events with native drivers. Here's how that looks:

import Animated, { useAnimatedScrollHandler, useSharedValue, runOnJS } from 'react-native-reanimated';

function YourFunctionalScrollComponent() {
  const scrollY = useSharedValue(0);

  const scrollHandler = useAnimatedScrollHandler({
    onScroll: (event) => {
      scrollY.value = event.contentOffset.y;
      // Since this runs on the native thread, use runOnJS to call JS functions like console.log
      runOnJS(console.log)("Updated scroll Y:", scrollY.value);
    },
  });

  return (
    <Animated.ScrollView
      scrollEventThrottle={16}
      showsVerticalScrollIndicator={false}
      onScroll={scrollHandler}
      useNativeDriver={true}
    >
      {/* Your scrollable content goes here */}
    </Animated.ScrollView>
  );
}

Why Your Initial Attempts Failed

  • Accessing this.state.y._value: This is a private internal property of Animated.Value—React Native doesn't guarantee it will update when useNativeDriver: true (since animations run on the native thread, not the JS thread). Always use the value passed to the listener callback instead.
  • Misusing addListener: You stored the value in this._value but tried to print this.state.y._value instead. Also, you didn't clean up the listener, which could cause memory leaks.

内容的提问来源于stack exchange,提问作者arp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:27:48