英文:
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:
<ScrollView
...
onScrollAnimationEnd={yourFunctionHere}
/>
...
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 }) => {
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 = () => {
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 as ScrollView).scrollTo({
x: position.x,
y: position.y,
animated: true,
});
}
}}
/>
{texts}
</ScrollView>
</SafeAreaView>
);
};
Tested with current latest React Native version 0.71<br>
Thanks
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});
<SafeAreaView>
<ScrollView
scrollEventThrottle={1}
ref={myRef}
onScroll={e => {
if (
position.animatedStarted &&
e.nativeEvent.contentOffset.x === position.x &&
e.nativeEvent.contentOffset.y === position.y
) {
console.log('scrollTo animation ended');
}
}}>
....
</SafeAreaView>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论