如何在React Native中的scrollTo动画完成后运行一个函数?

huangapple go评论45阅读模式
英文:

How to run a function after scrollTo animation has finished in React Native?

问题

我想在动画完成后运行一个函数。我该如何做到这一点?

ref.current.scrollToOffset({ animated: true, offset: 0 })
英文:

I am using scrollTo along with animation. I want run a function after the animation is finished. How can I do that?

ref.current.scrollToOffset({ animated: true, offset: 0 })

答案1

得分: 2

新答案

要在滚动动画完成后运行一个函数,你需要在使用FlatList或ScrollView时使用onScrollAnimationEnd

例如:

     <ScrollView
        ...
        onScrollAnimationEnd={yourFunctionHere}
      />
    ... 

就是这样简单。

旧答案

由于问题中没有提供很多信息,我认为问题是关于一个独立动画的,然后我回答了这个:

如果你正在使用普通的React Native Animated,你可以通过将回调函数添加到.start()函数来实现:

 Animated.timing(yourValueHere, {
     toValue: 1,
     duration: 5000,
     easing: Easing.linear,
 }).start(({ finished }) => {
    if (finished) {
      ref.current.scrollToOffset({ animated: true, offset: 0 })
    }
 });

来自文档:

通过在动画上调用start()来启动动画。start()接受一个完成回调,在动画完成时或在动画在完成之前因为调用了stop()而停止时将被调用。

英文:

New answer

To run a function after the scroll animation is finished, you have to use the onScrollAnimationEnd in case you're using a FlatList or ScrollView.

For example:

     &lt;ScrollView
        ...
        onScrollAnimationEnd={yourFunctionHere}
      /&gt;
    ... 

Simply as that.

Old answer

Since the question did not have a lot of information, I thought the question was about an standalone animation, then I replied this:

If you're using the normal React Native Animated you can simply achieve that by adding a callback to the .start() function:

 Animated.timing(yourValueHere, {
     toValue: 1,
     duration: 5000,
     easing: Easing.linear,
 }).start(({ finished }) =&gt; {
    if (finished) {
      ref.current.scrollToOffset({ animated: true, offset: 0 })
    }
 });

From the docs:

> Animations are started by calling start() on your animation. start() takes a completion callback that will be called when the animation is done or when the animation is done because stop() was called on it before it could finish.

答案2

得分: 0

如果您可以跟踪位置并监听ScrollView的onScroll事件,那么可以实现这个功能。以下是示例代码。(点击按钮进行测试)

const App = () => {
  const myRef = useRef();
  const [position, setPosition] = useState({ x: 0, y: 0 });

  let texts = [];

  for (let i = 0; i < 200; i++) {
    texts.push(<Text key={i}>Item value is {i}</Text>);
  }

  return (
    <SafeAreaView>
      <ScrollView
        scrollEventThrottle={1}
        ref={myRef}
        onScroll={(e) => {
          if (
            e.nativeEvent.contentOffset.x === position.x &&
            e.nativeEvent.contentOffset.y === position.y
          ) {
            console.log('scrollTo animation ended');
          }
        }}>
        <Button
          title={'button'}
          onPress={(e) => {
            if (myRef && myRef.current) {
              const newPos = { x: 0, y: 400 };
              setPosition(newPos);
              myRef.current.scrollTo({
                x: newPos.x,
                y: newPos.y,
                animated: true,
              });
            }
          }}
        />
        {texts}
      </ScrollView>
    </SafeAreaView>
  );
};

Tested with current latest React Native version 0.71
Thanks :)

Edit:
当前版本中没有`onScrollAnimationEnd`我也找不到任何在动画结束时触发的事件但是根据功能我们可以实现这样的功能思路是每当使用动画滚动时我们需要存储位置和动画状态以便决定动画是否已结束

```jsx
const [position, setPosition] = useState({ x: 0, y: 0, animationStarted: false });
<SafeAreaView>
  <ScrollView
    scrollEventThrottle={1}
    ref={myRef}
    onScroll={(e) => {
      if (
        position.animationStarted &&
        e.nativeEvent.contentOffset.x === position.x &&
        e.nativeEvent.contentOffset.y === position.y
      ) {
        console.log('scrollTo animation ended');
      }
    }}>
  // 其他部分...
</SafeAreaView>
英文:

If you can keep track of the position and listen to onScroll event of ScrollView, then it can be done.<br>
Here is the example code.(Click the button to test)<br>
Note: You may need to click again if first time click doesn't work.

const App = () =&gt; {
const myRef = useRef();
const [position, setPosition] = useState({x: 0, y: 0});
let texts = [];
for (let i = 0; i &lt; 200; i++) {
texts.push(&lt;Text key={i}&gt;Item value is {i}&lt;/Text&gt;);
}
return (
&lt;SafeAreaView&gt;
&lt;ScrollView
scrollEventThrottle={1}
ref={myRef}
onScroll={e =&gt; {
if (
e.nativeEvent.contentOffset.x === position.x &amp;&amp;
e.nativeEvent.contentOffset.y === position.y
) {
console.log(&#39;scrollTo animation ended&#39;);
}
}}&gt;
&lt;Button
title={&#39;button&#39;}
onPress={e =&gt; {
if (myRef &amp;&amp; myRef.current) {
const newPos = {x: 0, y: 400};
setPosition(newPos);
(myRef.current as ScrollView).scrollTo({
x: position.x,
y: position.y,
animated: true,
});
}
}}
/&gt;
{texts}
&lt;/ScrollView&gt;
&lt;/SafeAreaView&gt;
);
};

Tested with current latest React Native version 0.71<br>
Thanks 如何在React Native中的scrollTo动画完成后运行一个函数?

Edit:<br>
There's no onScrollAnimationEnd in the current version and neither I could find any event that is fired when the animation ends.<br>
But given the features, we can implement such functionality.
The idea is whenever we scroll with animation, we need to store the position and animation state, so that we can decide if the animation is ended or not.

const [position, setPosition] = useState({x: 0, y: 0,animationStarted: false});
&lt;SafeAreaView&gt;
&lt;ScrollView
scrollEventThrottle={1}
ref={myRef}
onScroll={e =&gt; {
if (
position.animatedStarted &amp;&amp;
e.nativeEvent.contentOffset.x === position.x &amp;&amp;
e.nativeEvent.contentOffset.y === position.y
) {
console.log(&#39;scrollTo animation ended&#39;);
}
}}&gt;
....
&lt;/SafeAreaView&gt;

huangapple
  • 本文由 发表于 2023年6月5日 20:55:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76406636.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定